【问题标题】:Qt Beginner QPainter and QRectQt 初学者 QPainter 和 QRect
【发布时间】:2012-12-31 11:58:14
【问题描述】:

我将如何绘制一个矩形?

我尝试了两种不同的方法;

void MyWidget::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    QRect rect = QRect(290, 20, 70, 40);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

这很好用(即使参数没有命名也没有使用),但我不想使用 QPaintEvent * 我没有用它。

所以我尝试重命名我的函数;

void MyWidget::draw()
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    QRect rect = QRect(290, 20, 70, 40);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

这不显示任何内容(但没有错误)。

如果我不使用 QPaintEvent * 为什么它不起作用??

【问题讨论】:

  • 你为什么期望一个随机命名的函数被调用来做任何事情?你的第一种方法很好。不命名(还)不需要的参数是合法且惯用的 C++。
  • 好的,如果我没有参数,是否有可能让第一个方法工作,但保持其他参数不变?
  • 不,不管你是否使用它,这个参数都是必需的。我不明白您为什么要删除它 - 忽略它不会花费您任何费用。
  • 它稍后会在我的代码中给我带来问题,我传递了其他参数,即 const QString &data。有没有另一种方法来绘制一个矩形,而不是使用事件参数?感谢您的回复。
  • 事件函数的签名是固定的,您根本无法更改它们(除了可能添加具有默认值的参数,但即使它有效,我也不会这样做)。您需要在问题中更详细地描述您的问题,看起来您正在尝试以“错误的方式”做某事。

标签: qt qpainter qrect


【解决方案1】:

绘制事件是绘制系统在需要重绘小部件时调用的方法。这就是为什么简单地命名自己的方法是行不通的。油漆系统永远不会调用它。

您确实应该使用QPaintEvent。它为您提供了需要绘制的矩形。该矩形将基于小部件的大小,因此不要在您的绘制事件中使用显式矩形,而是将您的小部件设置为正确的大小。如果您的小部件移动、调整大小等,将生成一个绘制事件。

void MyWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = event->rect();
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

现在,如果您想将绘制逻辑分离到另一个方法中,那很好。但是您需要从绘画事件中调用它:

void MyWidget::paintEvent(QPaintEvent *event)
{
    QRect rect = event->rect();
    draw(rect);
}

void MyWidget::draw(QRect &rect)
{
    QPainter painter(this);
    painter.setRenderHint(QPainter::Antialiasing);
    painter.setPen(Qt::black);
    painter.drawText(rect, Qt::AlignCenter,
                      "Data");
    painter.drawRect(rect);
}

如果您想完全绕过您所说的绘制事件,并且只想创建一个静态矩形来显示,一种方法是将其绘制到像素图并在 QLabel 中显示:

QPixMap pix(200,100);
QPainter painter(&pix);
// do paint operations
painter.end()
someLabel.setPixmap(pix)

【讨论】:

  • 哇,谢谢你的提示:)你是明星!!这正是我要找的!
  • 虽然您的第一个解决方案看起来很优雅,但您的解决方案实际上只是转换了从事件继承的区域,并且只是增加了对堆栈的调用,用户应该始终在外部设置您的“数据”函数,所以我认为这个双重调用,没有用。很抱歉不同意您的第一个解决方案。您的第二个简单解决方案看起来不错。
【解决方案2】:

您的paintEvent() 需要的任何数据都应该可以作为包含类的字段访问,在您的情况下,应该是MyWidget 的私有字段。这些私有字段可以通过“setters”暴露给MyWidget的客户,这将在MyWidget上调用update()之前设置数据值,这将触发对paintEvent()的调用。

【讨论】:

    【解决方案3】:

    This playlist 包含最好的 Qt 教程,从教程 74 开始对你有用(Qpainter 和 QPen),教程 75 是如何使用 QRect 绘制矩形。

    【讨论】:

    • 谢谢,我去看看。
    【解决方案4】:

    @Mat 也告诉过你:"event" 是启动画家的正确方法。
    QPainter 只能在 QPaintEvent 事件之后调用,该事件带有可以绘制对象的安全区域

    因此,您必须找到另一种传输数据的策略,以帮助 我会提出一个简单的方法,可以适应很多情况。

    widget.cpp

    #include <QtGui>
    #include "widget.h"
    
    #define MIN_DCX    (0.1)
    #define MAX_DCX    (5.0)
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
    {    
        dcx=MIN_DCX;
        setFixedSize(170, 100);
    }
    
    void Widget::paintEvent(QPaintEvent *event)
    {
        Q_UNUSED(event); 
        QPainter painter;
        painter.begin(this);
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setPen(Qt::black);
        pcx=dcx*2;
        QRect rect = QRect(50-dcx,25-dcx,60+pcx,40+pcx);
        painter.drawText(rect, Qt::AlignCenter,printData);
        painter.drawRect(rect);
        painter.end();
    
    }
    
    void Widget::setPrintData(QString value){
       printData = value;
       dcx=(dcx>MAX_DCX)?MIN_DCX:dcx+MIN_DCX;
    }
    

    widget.h

    #ifndef WIDGET_H
    #define WIDGET_H
    
    #include <QWidget>
    
    class Widget : public QWidget
    {
        Q_OBJECT
    
    public:
        Widget(QWidget *parent);
        void setPrintData(QString value);
    
    protected:
        void paintEvent(QPaintEvent *event);
    
    private:
        QString printData;
        float dcx;
        float pcx;
    };
    
    
    #endif
    

    window.cpp

    #include <QtGui>
    #include "widget.h"
    #include "window.h"
    
    #define MAX_SDCX  20
    
    Window::Window()
        : QWidget()
    {
        gobject = new Widget(this);
    
        textMode=1;
        rectMode=1;
        gobject->setPrintData(msgs[textMode]);
    
        QGridLayout *layout = new QGridLayout;
        layout->addWidget(gobject, 0, 0);
        setLayout(layout);
    
        QTimer *timer = new QTimer(this);
        connect(timer, SIGNAL(timeout()), this, SLOT(dataOnAir()));
        timer->start(10);
    
        setWindowTitle(tr("Rect Shaking"));
    }
    
    
    
    void Window::dataOnAir(){
        if((++rectMode)>MAX_SDCX){
            rectMode=0;
            textMode^=1;
        }
        gobject->setPrintData(msgs[textMode]);
        gobject->repaint();
    }
    

    window.h

    #ifndef WINDOW_H
    #define WINDOW_H
    
    #include <QWidget>
    #include "widget.h"
    
    class Window : public QWidget
    {
        Q_OBJECT
    
    public:
        Window();
    
    private slots:
        void dataOnAir();
    
    private:
        Widget *gobject;
        const QString msgs[2] = {"Hello","World"};
        int textMode;
        int rectMode;
    };
    
    #endif
    

    ma​​in.cpp

    #include <QApplication>
    #include "window.h"
    
    int main(int argc, char *argv[])
    {
        QApplication app(argc, argv);
        Window window;
        window.show();
        return app.exec();
    }
    

    正如您在代码中看到的那样,在“小部件”对象之外执行了一个计时器

    每 10 毫秒发送一次重绘小部件以重绘具有不同大小的“矩形”,并且每 20 个周期(200 毫秒)将文本“hello”更改为“world”

    在这个例子中你可以看到无论如何都需要覆盖 QPainterDevice 架构。

    您可能还注意到“paintEvent”中的“事件”被静音而不是直接使用,但必须执行序列QPainter。 p>

    【讨论】:

    • 我很抱歉,如果有些争论似乎重新排序,我昨天在欧洲中部时间 22:00 开始写回复,但是我必须去吃“新年”晚餐,现在我回来了,并发布完整的回复。我没有看到其他人有写作..对不起。祝大家新年快乐!
    • 新年快乐!感谢您的帮助:)
    【解决方案5】:

    覆盖小部件的paintEvent() 函数使您能够自定义小部件,并且该函数会定期调用以重绘小部件。因此,任何绘图都应在此功能中进行。然而,覆盖 paintEvent() 可能会导致一些性能问题。我更喜欢使用 QGraphicsScene 和 QGraphicsView 然后我会在场景中添加一个矩形,这是做这种绘图的常用方法。请检查 GraphicsView 框架

    http://qt-project.org/doc/qt-4.8/graphicsview.html

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-09
      • 1970-01-01
      • 2020-12-19
      • 2023-03-27
      • 1970-01-01
      • 2014-01-01
      相关资源
      最近更新 更多