按住鼠标按钮时如何绘制?

时间:2016-09-06 21:52:10

标签: c++ qt

我正在尝试创建一个简单的绘图应用程序 - 它只是在您单击并拖动光标时绘制(就像Paint一样)。我知道我必须使用QPainter,但我该如何处理呢?怎么做?任何帮助将非常感激。我尝试潜伏在互联网上,但没有找到太多的信息(我通过启动应用程序的代码来绘制线条等等,但是我找不到用户绘制内容的示例)。

2 个答案:

答案 0 :(得分:3)

这是Jeremy在代码而不是散文中的回答:

// https://github.com/KubaO/stackoverflown/tree/master/questions/simplepaint-39358392
#include <QtWidgets>

// Make a subclass of the QWidget class, so that you can override some of its 
// virtual methods
class PaintWidget : public QWidget {
    // Create a QPixmap object that you will use to store the bitmap 
    // that the user will draw [on].
    QPixmap m_pixmap;
    QPoint m_lastPos;
    // Override the paintEvent(QPaintEvent *) [...]
    void paintEvent(QPaintEvent *) override {
        QPainter painter{this};
        painter.drawPixmap(0, 0, m_pixmap);
    }
    void resizeEvent(QResizeEvent *) override {
        // [...] size the QPixmap to be at least as big as the maximum size of the window
        // We'll also never let it shrink so as not to lose the already drawn image.
        auto newRect = m_pixmap.rect().united(rect());
        if (newRect == m_pixmap.rect()) return;
        QPixmap newPixmap{newRect.size()};
        QPainter painter{&newPixmap};
        painter.fillRect(newPixmap.rect(), Qt::white);
        painter.drawPixmap(0, 0, m_pixmap);
        m_pixmap = newPixmap;
    }
    // Override the mousePressEvent(QMouseEvent *) [...]
    void mousePressEvent(QMouseEvent * ev) override {
        m_lastPos = ev->pos();
        draw(ev->pos());
    }
    // Override the mouseMoveEvent(QMouseEvent *) [...]
    void mouseMoveEvent(QMouseEvent * ev) override {
        draw(ev->pos());
    }
    void draw(const QPoint & pos) {
        QPainter painter{&m_pixmap};
        painter.setRenderHint(QPainter::Antialiasing);
        painter.setPen({Qt::blue, 2.0});
        painter.drawLine(m_lastPos, pos);
        m_lastPos = pos;
        update();
    }
public:
    using QWidget::QWidget;
};

int main(int argc, char ** argv) {
    QApplication app{argc, argv};
    // Create an object of your subclass and call show()
    PaintWidget ui;
    ui.show();
    return app.exec();
}

没有必要覆盖mouseReleaseEvent。在窗口小部件中,默认行为是仅在按下鼠标按钮时跟踪鼠标移动。除非按下按钮,否则mouseMoveEvent不会被呼叫。

答案 1 :(得分:2)

这是一个非常广泛的问题,但这里有基础知识:

  1. 创建QWidget类的子类,以便稍后可以覆盖其中的一些虚拟方法。
  2. 创建子类的对象并在其上调用show()(在调用QApplication::exec()之前)。此对象将在屏幕上显示为一个非常简单的窗口,它将作为用户的绘画表面。
  3. 创建一个QPixmap对象,用于存储用户将绘制的位图。确保将QPixmap的大小设置为至少与要支持的窗口的最大大小一样大。致电fill()上的QPixmap,用您喜欢的背景颜色填充它。
  4. 覆盖对象的mousePressEvent(QMouseEvent *)方法以设置布尔值is_mouse_down标志,并在窗口中记录鼠标指针的当前位置(通过调用pos()上的QMouseEvent传入mousePressEvent()调用并将其存储到对象的成员变量中的对象。)
  5. 覆盖mouseMoveEvent(QMouseEvent *)方法,以便如果is_mouse_down_is设置为true,则会在堆栈上创建一个QPainter对象 - 将指针传递给{{1} } QPixmap对象的构造函数,以便QPainter将绘制到您的QPainter对象中。然后在QPixmap对象上调用drawLine()以从上一个鼠标位置绘制一条线到当前鼠标位置。最后,请致电QPainter告诉Qt尽快为您致电update()
  6. 覆盖paintEvent()方法,将mouseReleaseEvent(QMouseEvent *)设置为false
  7. 重写is_mouse_down方法以在堆栈上创建paintEvent(QPaintEvent *)对象 - 将指向(QPainter)的指针传递给this对象的构造函数,这样它就会直接涂在QPainter上。然后在QWidget对象上调用drawPixmap(),以便将QPainter对象绘制到窗口小部件的可见表面上。
  8. 如果您想查看预先编写的示例,请查看QPixmap中Qt附带的Scribble应用程序。