2017-02-12 99 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