3

Qt 4.8.5 で次のバグを経験しました。

Mainwondow
-CentralWidget
--VerticalLayout
---TabWidget
---QLabel (コードで作成し、レイアウトに追加)
---StatusBar

フルスクリーン モードでは、TabWidget とステータスバーを非表示にすると、QLabel の更新が停止します。(更新を行うスレッドがあります) 奇妙なことに、TabWidget または StatusBar を復元すると正常に動作します。VerticalLayoutに1x1ピクセルのラベルを追加すると、うまく機能します。

GUI の変更を担当するスロット。

void Mainview::onToggleFullScreen()
{
    if (this->isFullScreen())
    {
        this->showNormal();
        this->statusbar->show();
        this->tabWidget->show();
    }
    else
    {
        this->showFullScreen();
        this->statusbar->hide();
        this->tabWidget->hide();
    }
}

しかし、画像の近くに QLabel を配置すると理解できないことは機能し、この 1 行を MainWindow コンストラクターに追加すると、更新が停止します。

label_10->hide(); //this is the label

何が問題なのですか?

(前もって感謝します)

4

1 に答える 1

0

おそらく何か間違った方法でやっているのでしょうが、コードを示していないので、どうすればわかりますか?

以下は、それを行う方法の安全なSSCCEです。Qt 4.8 と 5.1 の両方で動作します。

注意点: ステータス バーは!の一部であってはなりません。centralWidget()QMainWindowを提供statusBar()します。

スレッド間で画像を安全に渡す唯一の方法は、QImage. GUIスレッド以外では使用できませんQPixmap話はここまで。

以下の例では、すべての重要な処理が舞台裏で行われています。別のDrawThing QObjectスレッドに住んでいます。このメソッドQThreadのデフォルトの実装はrun()、メッセージ ループをスピンします。そのため、タイマーを起動できます。そのためには、回転するメッセージ ループが必要です。

新しいイメージが生成されるたびに、暗黙的に にメッセージをポストすることによって GUI スレッドに送信されますMainWindow。メッセージは Qt イベント ループ コードによって受信され、スロット呼び出しに再合成されます。DrawThing これは、接続 (およびインスタンス)の両端がMainWindow異なるスレッドに存在するためです。

Qt の「少ないコードでより多くの作成」アプローチの美しさ:) Qt の機能を活用すればするほど、ボイラープレートについて心配する必要がなくなります。

スクリーンショット

//main.cpp
#include <QMainWindow>
#include <QVBoxLayout>
#include <QStatusBar>
#include <QLabel>
#include <QThread>
#include <QPainter>
#include <QImage>
#include <QApplication>
#include <QBasicTimer>
#include <QPushButton>

class DrawThing : public QObject {
    Q_OBJECT
    int m_ctr;
    QBasicTimer t;
    void timerEvent(QTimerEvent * ev) {
        if (ev->timerId() != t.timerId()) return;
        QImage img(128, 128, QImage::Format_RGB32);
        QPainter p(&img);
        p.translate(img.size().width()/2, img.size().height()/2);
        p.scale(img.size().width()/2, img.size().height()/2);
        p.eraseRect(-1, -1, 2, 2);
        p.setBrush(Qt::NoBrush);
        p.setPen(QPen(Qt::black, 0.05));
        p.drawEllipse(QPointF(), 0.9, 0.9);
        p.rotate(m_ctr*360/12);
        p.setPen(QPen(Qt::red, 0.1));
        p.drawLine(0, 0, 0, 1);
        m_ctr = (m_ctr + 1) % 12;
        emit newImage(img);
    }
public:
    explicit DrawThing(QObject *parent = 0) : QObject(parent), m_ctr(0) { t.start(1000, this); }
    Q_SIGNAL void newImage(const QImage &);
};

class MainWindow : public QMainWindow {
    Q_OBJECT
    QLabel *m_label;
public:
    explicit MainWindow(QWidget *parent = 0, Qt::WindowFlags flags = 0) : QMainWindow(parent, flags) {
        QWidget * cw = new QWidget;
        QTabWidget * tw = new QTabWidget();
        QVBoxLayout * l = new QVBoxLayout(cw);
        l->addWidget(tw);
        l->addWidget(m_label = new QLabel("Label"));
        setCentralWidget(cw);
        QPushButton * pb = new QPushButton("Toggle Status Bar");
        tw->addTab(pb, "Tab 1");
        connect(pb, SIGNAL(clicked()), SLOT(toggleStatusBar()));
        statusBar()->showMessage("The Status Bar");
    }
    Q_SLOT void setImage(const QImage & img) {
        m_label->setPixmap(QPixmap::fromImage(img));
    }
    Q_SLOT void toggleStatusBar() {
        statusBar()->setHidden(!statusBar()->isHidden());
    }
};

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    QThread t;
    DrawThing thing;
    MainWindow w;
    thing.moveToThread(&t);
    t.start();
    w.connect(&thing, SIGNAL(newImage(QImage)), SLOT(setImage(QImage)));
    w.show();
    t.connect(&a, SIGNAL(aboutToQuit()), SLOT(quit()));
    int rc = a.exec();
    t.wait();
    return rc;
}

#include "main.moc"
于 2013-08-26T18:42:05.883 に答える