我正在尝试制作一个应用程序,您可以在其中用手指在画布上绘画。
为了实现这一点,我将QWidgetas子类化MFCanvas,在 QML 中使用 注册类
qmlRegisterType<>(),实现虚paintEvent();函数,并在函数内部
绘制它。
问题:
在构建时,抛出此警告:QPainterpaintEvent();
QPainter
QWidget::paintEngine: 不应再被调用
然后,抛出几个其他相关警告:
QPainter::begin: Paint device returned engine == 0, type: 1
QPainter::setPen: Painter not active
Run Code Online (Sandbox Code Playgroud)
难怪:QPainter什么都没画……
还有,我应该自己打电话paintEvent();吗?
还是应该每帧都调用它QWidget,而我却以某种方式把它搞砸了?
我在网上搜索,但我发现的所有帖子都没有答案,或者他们
使用的不是QWidget.
我的代码:
mfcanvas.cpp:
#include "mfcanvas.h"
#include <QDebug>
#include <QPainter>
#include <QVector2D>
#include <QList>
MFCanvas::MFCanvas(QWidget *parent) : QWidget(parent)
{
paths = new QList<QList<QVector2D>*>();
current = NULL;
QWidget::resize(100, 100);
}
MFCanvas::~MFCanvas()
{
delete paths;
}
void MFCanvas::paintEvent(QPaintEvent *)
{
if(current!=NULL){
if(current->length() > 1){
QPainter painter(this);
painter.setPen(Qt::black);
for(int i = 1; i < current->length(); i++){
painter.drawLine(current->at(i-1).x(), current->at(i-1).y(), current->at(i).x(), current->at(i).y());
}
}
}
}
void MFCanvas::pressed(float x, float y)
{
if(current==NULL){
qDebug() << "null:"<<current;
current = new QList<QVector2D>();
current->append(QVector2D(x, y));
}else{
qDebug() << "current:"<<current;
}
paintEvent(NULL);
}
void MFCanvas::update(float x, float y)
{
current->append(QVector2D(x, y));
}
void MFCanvas::resize(int w, int h)
{
QWidget::resize(w, h);
}
Run Code Online (Sandbox Code Playgroud)
主.cpp:
#include <QApplication>
#include <QQmlApplicationEngine>
#include <QtQml>
#include <QSurfaceFormat>
#include "creator.h"
#include "mfcanvas.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
qmlRegisterType<MFCanvas>("com.cpp.mfcanvas", 1, 0, "MFCanvas");
QQmlApplicationEngine engine;
QQmlComponent *component = new QQmlComponent(&engine);
QObject::connect(&engine, SIGNAL(quit()), QCoreApplication::instance(), SLOT(quit()));
Creator creator(component);
QObject::connect(component, SIGNAL(statusChanged(QQmlComponent::Status)), &creator, SLOT(create(QQmlComponent::Status)));
component->loadUrl(QUrl("qrc:///main.qml"));
int rv;
rv = app.exec();
delete component;
return rv;
}
Run Code Online (Sandbox Code Playgroud)
创建者.cpp:
#include "creator.h"
#include <QQuickWindow>
#include <QDebug>
Creator::Creator(QQmlComponent *component)
{
this->component = component;
}
void Creator::create(QQmlComponent::Status status)
{
if(status == QQmlComponent::Ready){
QObject *topLevel = component->create();
QQuickWindow::setDefaultAlphaBuffer(true);
QQuickWindow *window = qobject_cast<QQuickWindow *>(topLevel);
QSurfaceFormat surfaceFormat = window->requestedFormat();
window->setFormat(surfaceFormat);
window->show();
}
}
Run Code Online (Sandbox Code Playgroud)
main.qml:(重要部分)
import QtQuick 2.2
import QtQuick.Controls 1.1
import QtQuick.Controls.Styles 1.2
import QtQuick.Layouts 1.1
import QtQuick.Window 2.0
import com.cpp.mfcanvas 1.0
ApplicationWindow {
visible: true
width: 640
height: 480
title: qsTr("MFCanvas")
onSceneGraphInitialized: {
drawMenu.visible = true;
lineWidth.visible = true;
colorMenu.visible = true;
drawMenu.visible = false;
lineWidth.visible = false;
colorMenu.visible = false;
}
Rectangle {
id: main
anchors.fill: parent
property real toolsH: 15
property real iconW: 25
property real menuH: 8
property real menuW: 16
property real dpi: (Screen.logicalPixelDensity == undefined ? 6 : Screen.logicalPixelDensity) * 1.5
property color choosenColor: Qt.hsla(hue.value, saturation.value, luminance.value, 1)
Text {
anchors.centerIn: parent
font.pointSize: 60
text: "MFCanvas"
}
MFCanvas {
id: canvas
Component.onCompleted: {
canvas.resize(main.width, main.height);
}
}
//...
}
}
Run Code Online (Sandbox Code Playgroud)
如果您需要任何其他信息,请告诉我。
先感谢您!=)
小智 7
这很好地解释了here:
https://forum.qt.io/topic/64693
简而言之:不要尝试直接从输入事件处理程序中绘制,而是重载小部件中的paintEvent 方法并在那里创建QPainter。专门使用输入事件来修改内部数据模型,并在paintEvent中使用QPainter来显示它,在输出路径上。
我自己找到了一个简单的解决方案:
不是从 QWidget 派生,而是从 QQuickPaintedItem 派生。QQuickPaintedItem 是一个完全满足我需要的类:使用 QPainter 在 QML-Element 上绘画。这是代码(缩小到基本部分):
mfcanvas.h:
class MFCanvas : public QQuickPaintedItem
{
Q_OBJECT
public:
explicit MFCanvas(QQuickItem *parent = 0);
~MFCanvas();
protected:
void paint(QPainter *painter);
Run Code Online (Sandbox Code Playgroud)
mfcanvas.cpp:
void MFCanvas::paint(QPainter *painter)
{
painter->translate(-translation.x(), -translation.y());
//...
}
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,提供了一个简单的paint()函数,它将一个指向QPainter的指针移交给可供使用的。=)
| 归档时间: |
|
| 查看次数: |
29422 次 |
| 最近记录: |