2017-02-12 52 views
0

我必須在透明Qt窗口的不同位置顯示矩形。 在顯示窗口之前,我設置了新的矩形位置。有時舊的位置會顯示幾毫秒。 (例如,m_y_pos = 100而不是m_y_pos = 400)。看來在顯示窗口和更新窗口之間存在種族差異。QWidget/QPainter show()+ paintEvent() - >在舊位置顯示矩形

我希望有人知道一個建議。

由於紙漿

示例代碼:

#include <QApplication> 
#include <QtWidgets/QMainWindow> 
#include <QPaintEvent> 
#include <QTimer> 
#include <QDebug> 
#include <QPainter> 

class QtGuiApplication : public QMainWindow 
{ 
    Q_OBJECT 

public: 
    int m_x_pos; 
    int m_y_pos; 
    QTimer* m_timer; 

    QtGuiApplication(QWidget *parent = Q_NULLPTR) : QMainWindow(parent), m_x_pos(100), m_y_pos(100) 
    { 
    setGeometry(100, 100, 1000, 1000); 

    //Make Window transparent 
    setAttribute(Qt::WA_NoSystemBackground, true); 
    setAttribute(Qt::WA_TranslucentBackground); 
    setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus); 

    m_timer = new QTimer(this); 
    m_timer->setInterval(500); 
    m_timer->start(); 
    connect(m_timer, &QTimer::timeout, this, &QtGuiApplication::Tick); 
    } 

    private slots: 

    //toggle visibility of the window to show the effect 
    void Tick() 
    { 
    if (isVisible()) 
    { 
     hide(); 
    } 
    else 
    { 
     //Set new position before showing the window 
     m_y_pos = m_y_pos == 100 ? 400 : 100; 
     show(); 
    } 
    } 

    //Paint rectangles at different positions 
    void paintEvent(QPaintEvent* event) 
    { 
    QPainter painter(this); 

    painter.setBrush(Qt::red); 
    painter.setPen(Qt::black); 

    for (int i = 0; i < event->rect().width(); i += 50) 
    { 
     painter.drawRect(m_x_pos + i, m_y_pos, 30, 30); 
    } 
    } 

}; 

int main(int argc, char *argv[]) 
{ 
    QApplication a(argc, argv); 
    QtGuiApplication w; 
    w.show(); 
    return a.exec(); 
} 
+0

我不能在這裏重現您的問題,但一般而言,您應通過調用'更新通知,您的窗口小部件需要更新的塗料體系()'每當改變你的widget的外觀參數變化。 (即在'Tick()'中設置'm_y_pos'後直接在你的情況下) – E4z9

+0

行爲只能在啓用了Aero的Windows 7下重現。 – pulp

回答

0

你缺乏改變位置後調用update()。通常,這應該被分解爲setPos方法。

一旦你這樣做,hide()show()不再是必要的:每個setPos調用將根據需要更新小部件。

您應該從滿足您需求的最基本類別中獲得:QWidget。畢竟,你並沒有使用任何功能QMainWindow

// https://github.com/KubaO/stackoverflown/tree/master/questions/rect-paint-42194052 
#include <QtWidgets> 

class Window : public QWidget 
{ 
    QPointF m_pos{100, 100}; 
    void paintEvent(QPaintEvent* event) override 
    { 
     QPainter painter(this); 
     painter.setBrush(Qt::red); 
     painter.setPen(Qt::black); 
     for (int i = 0; i < event->rect().width(); i += 50) 
     painter.drawRect(QRectF(m_pos.x() + i, m_pos.y(), 30, 30)); 
    } 
public: 
    Window(QWidget *parent = nullptr) : QWidget(parent) 
    { 
     setAttribute(Qt::WA_NoSystemBackground, true); 
     setAttribute(Qt::WA_TranslucentBackground); 
     setWindowFlags(Qt::Tool | Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint 
        | Qt::WindowTransparentForInput | Qt::WindowDoesNotAcceptFocus); 
    } 
    void setPos(const QPointF & pos) { 
     m_pos = pos; 
     update(); 
    } 
}; 

int main(int argc, char ** argv) { 
    QApplication app{argc, argv}; 
    Window w; 
    QTimer timer; 
    QObject::connect(&timer, &QTimer::timeout, [&w]{ 
     static bool toggle{}; 
     if (!w.isVisible()) { 
     toggle = !toggle; 
     if (toggle) 
      w.setPos({200, 200}); 
     else 
      w.setPos({100, 100}); 
     }; 
     w.setVisible(!w.isVisible()); 
    }); 
    timer.start(500); 
    w.resize(1000, 500); 
    return app.exec(); 
} 
+0

感謝您的解決方案。我測試了它:效果仍然存在(Windows 7,啓用Aero),因爲如果窗口不可見,則update()不起作用。此刻我使用了一種解決方法:我移動屏幕的窗口而不是隱藏它。 (是的壞...) – pulp

+0

然後這是一個Qt錯誤。 –

+0

創建錯誤報告:https://bugreports.qt.io/browse/QTBUG-58911 – pulp