关于QPaintDevice的问题

古月河图 2016-05-10 11:39:40
各位好,我是一个Qt的初学者,在学习QPainter的过程中遇到了如下的问题
先附上代码:
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyWindow(QMainWindow):
def __init__(self):
super(MyWindow, self).__init__()
self.setFixedSize(400, 400)
self.scrollarea = QScrollArea(self)
self.scrollarea.setFixedSize(300, 300)
self.show()

def paintEvent(self, event):

# 在QMainWindow上绘图,正常运行
# qp = QPainter(self)

# 在QScrollArea上绘图,提示错误
qp = QPainter(self.scrollarea)

# 蓝色,粗细为2,实线
pen = QPen(Qt.blue, 2, Qt.SolidLine)
qp.setPen(pen)
# 画一个直径400的圆
qp.drawEllipse(0, 0, 400, 400)

app = QApplication(sys.argv)
win = MyWindow()
sys.exit(app.exec_())

我建立一个400*400的QMainWindow,然后在之上有放入了一个300*300的QScrollArea,然后我想在QScrollArea里面画一个直径400的圆,问题来了,现在只能在QMainWindow上画圆,一旦我将QPainter的device改成scrollarea,程序就是一直提示
QPainter::begin: Widget painting can only begin as a result of a paintEvent


我是没辙了。。。

诚心请教,我该如何把圆画到QScrollArea里面??
...全文
315 10 打赏 收藏 转发到动态 举报
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
古月河图 2016-05-16
  • 打赏
  • 举报
回复
我自己找到原因了 是因为我偷懒没写
if __name__ == "__main__":
再次感谢你
dianyancao 2016-05-15
  • 打赏
  • 举报
回复
没有哦
古月河图 2016-05-15
  • 打赏
  • 举报
回复
非常感谢你的解答,问题解决了。。 但是还是有个小问题 如果直接转换,还是会提示 NameError: global name 'MyItem' is not defined 的错误 我不知道怎么来的 必须我手动把import命令换个位置,才正常运行,你有遇到这种情况吗??
dianyancao 2016-05-14
  • 打赏
  • 举报
回复
回复内容字数限制,不能连续回复三次以上 qt的designer界面可以将一个控件提升为自定义的类 用designer打开.ui文件,并右键要提升的控件选择Promted to ...,填写Promoted class name,并Add,接着选择刚加入的类,点击Promote完成提升 我用的.ui文件内容如下: MyPaintWidget.ui
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>MyPaintWidget</class>
 <widget class="QWidget" name="MyPaintWidget">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>201</width>
    <height>221</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>画图</string>
  </property>
  <widget class="QPushButton" name="pushButtonClearTheChar">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>190</y>
     <width>91</width>
     <height>23</height>
    </rect>
   </property>
   <property name="text">
    <string>Clear</string>
   </property>
  </widget>
  <widget class="QSpinBox" name="spinBoxDrawWidth">
   <property name="geometry">
    <rect>
     <x>70</x>
     <y>0</y>
     <width>42</width>
     <height>16</height>
    </rect>
   </property>
  </widget>
  <widget class="MyLabel" name="labelTheChar">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>20</y>
     <width>181</width>
     <height>161</height>
    </rect>
   </property>
   <property name="palette">
    <palette>
     <active>
      <colorrole role="Base">
       <brush brushstyle="SolidPattern">
        <color alpha="255">
         <red>255</red>
         <green>255</green>
         <blue>255</blue>
        </color>
       </brush>
      </colorrole>
      <colorrole role="Window">
       <brush brushstyle="SolidPattern">
        <color alpha="255">
         <red>0</red>
         <green>0</green>
         <blue>0</blue>
        </color>
       </brush>
      </colorrole>
     </active>
     <inactive>
      <colorrole role="Base">
       <brush brushstyle="SolidPattern">
        <color alpha="255">
         <red>255</red>
         <green>255</green>
         <blue>255</blue>
        </color>
       </brush>
      </colorrole>
      <colorrole role="Window">
       <brush brushstyle="SolidPattern">
        <color alpha="255">
         <red>0</red>
         <green>0</green>
         <blue>0</blue>
        </color>
       </brush>
      </colorrole>
     </inactive>
     <disabled>
      <colorrole role="Base">
       <brush brushstyle="SolidPattern">
        <color alpha="255">
         <red>0</red>
         <green>0</green>
         <blue>0</blue>
        </color>
       </brush>
      </colorrole>
      <colorrole role="Window">
       <brush brushstyle="SolidPattern">
        <color alpha="255">
         <red>0</red>
         <green>0</green>
         <blue>0</blue>
        </color>
       </brush>
      </colorrole>
     </disabled>
    </palette>
   </property>
   <property name="autoFillBackground">
    <bool>true</bool>
   </property>
   <property name="text">
    <string>TextLabel</string>
   </property>
   <property name="alignment">
    <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
   </property>
  </widget>
  <widget class="QLabel" name="labelDrawWidth">
   <property name="geometry">
    <rect>
     <x>10</x>
     <y>0</y>
     <width>61</width>
     <height>16</height>
    </rect>
   </property>
   <property name="text">
    <string>画笔粗细:</string>
   </property>
  </widget>
 </widget>
 <customwidgets>
  <customwidget>
   <class>MyLabel</class>
   <extends>QLabel</extends>
   <header>mylabel.h</header>
  </customwidget>
 </customwidgets>
 <resources/>
 <connections/>
</ui>
古月河图 2016-05-13
  • 打赏
  • 举报
回复
在 MyPaintWidget.py 文件当中
self.labelTheChar = MyLabel(MyPaintWidget)
是如何做到的呢? 是你后期添加的,还是直接通过ui文件转换过来的??
dianyancao 2016-05-11
  • 打赏
  • 举报
回复
用QT试了QScrollArea不能直接在其上绘图,所以继承QWidget创建子类对象myWidget将其添加到QScrollArea上绘图
#coding:utf-8

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
 
class MyWindow(QMainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setFixedSize(400, 400)
        self.scrollArea = QScrollArea(self)
        self.scrollArea.setFixedSize(300, 300)
        self.myWidget = MyWidget()
        self.myWidget.setFixedSize(400,400)
        self.scrollArea.setWidget(self.myWidget)
        self.scrollArea.show()
        self.show()

class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()
    def paintEvent(self, event):
        qp = QPainter(self)
        # 蓝色,粗细为2,实线
        pen = QPen(Qt.blue, 2, Qt.SolidLine)
        qp.setPen(pen)
        # 画一个直径400的圆
        qp.drawEllipse(0, 0, 400, 400)

app = QApplication(sys.argv)
win = MyWindow()
sys.exit(app.exec_())
我也初学python,有另外的方法创建自定义的类包含QLabel,QPainter,QPixmap在paintEvent外绘图,实现比较难看,弄ing。。
dianyancao 2016-05-11
  • 打赏
  • 举报
回复
用Qt测试了QScrollArea,不能直接在其上绘图 所以创建了一个子类MyWidget将其添加到QScrollArea后,在myWidget上绘图
#coding:utf-8
import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *
 
class MyWindow(QMainWindow):
    def __init__(self):
        super(MyWindow, self).__init__()
        self.setFixedSize(400, 400)
        self.scrollArea = QScrollArea(self)
        self.scrollArea.setFixedSize(300, 300)
        self.myWidget = MyWidget()
        self.myWidget.setFixedSize(400,400)
        self.scrollArea.setWidget(self.myWidget)
        self.scrollArea.show()
        self.show()

class MyWidget(QWidget):
    def __init__(self):
        super(MyWidget, self).__init__()
    def paintEvent(self, event):
        qp = QPainter(self)
        # 蓝色,粗细为2,实线
        pen = QPen(Qt.blue, 2, Qt.SolidLine)
        qp.setPen(pen)
        # 画一个直径400的圆
        qp.drawEllipse(0, 0, 400, 400)

app = QApplication(sys.argv)
win = MyWindow()
sys.exit(app.exec_())
我也初学python,有另外的方案用自定义的类包含QLabel,QPainter,QPixmap在paintEvent外绘图,实现很难看,正在弄。。
dianyancao 2016-05-11
  • 打赏
  • 举报
回复
网站又抽风了。。 弄了一个下午,用pyqt4实现了一个简单的画图程序,运行MyWidget.py,左键画白色线条,右键用黑色擦除 一共创建了四个文件,MyLabel.py,MyWidget.py,其中MyPaintWidget.py由MyPaintWidget.ui用pyuic4工具生成 需要将MyPaintWidget.py中小写的from mylabel import MyLabel替换为from MyLabel import MyLabel 具体文件内容如下: MyLabel.py
from PyQt4.QtCore import *
from PyQt4.QtGui import *

class MyLabel(QLabel):
    def __init__(self,parent = None):
        super(MyLabel,self).__init__(parent)
        self._drawText = QString()
        self._painter = QPainter()
        self._backColor = QColor(0,0,0)
        self._pen = QPen(self._backColor)
        self._pixmap = QPixmap()
        self._mouseLastX = int()
        self._mouseLastY = int()
        self._mouseDownX = int()
        self._mouseDownY = int()
    @pyqtSlot()
    def clear(self):
        super(MyLabel,self).clear()
        self._pixmap.fill(self._backColor)
        super(MyLabel,self).setPixmap(self._pixmap)
        self.update()

    def setGeometry(self, rect):
        super(MyLabel,self).setGeometry(rect)
        self._pixmap = QPixmap(rect.size())
        self.clear()
    def setPen(self,pen):
        self._pen = pen
        if self._painter.isActive():
            self._painter.setPen(pen)
    def setBackColor(self,color):
        self._backColor = color
        self.clear(self)
    def beginPaint(self):
        if not self._pixmap.size().isEmpty():
            self._painter.begin(self._pixmap)
            self.setPen(self._pen)
    def endPaint(self):
        if self._painter.isActive():
            self._painter.end()
            self.update()
    def setPixmap(self,pixmap):
        self._pixmap = pixmap
        self.update()
    def mousePressEvent(self,ev):
        self.emit(SIGNAL('on_mousePress'),ev)
        self._mouseLastX = ev.x()
        self._mouseLastY = ev.y()
        self._mouseDownX = self._mouseLastX
        self._mouseDownY = self._mouseDownY
    def mouseMoveEvent(self,ev):
        self.emit(SIGNAL('on_mouseMove'),ev)
        #self._signal_on_mouseMove.emit()
        self._mouseLastX = ev.x()
        self._mouseLastY = ev.y()
    def mouseReleaseEvent(self,ev):
        self.emit(SIGNAL('on_mouseRelease'),ev)
        #self._signal_on_mouseRelease.emit()
    def paintEvent(self,ev):
        self._painter.begin(self)
        self._painter.drawPixmap(QPoint(0,0),self._pixmap)
        self._painter.drawText(self._pixmap.rect(),Qt.AlignCenter,self._drawText)
        self._painter.end()
MyWidget.py
#coding:utf-8

import sys
from PyQt4.QtCore import *
from PyQt4.QtGui import *

from MyPaintWidget import Ui_MyPaintWidget
class MyWidget(QWidget):
    def __init__(self,parent = None):
        super(MyWidget,self).__init__(parent)
        self.ui = Ui_MyPaintWidget()
        self.ui.setupUi(self)
        self.labelTheChar = self.ui.labelTheChar
        self.spinBoxDrawWidth = self.ui.spinBoxDrawWidth
        self.show()
    def on_mouseMove(self,ev):
        self.labelTheChar.beginPaint()
        if ((ev.buttons() & Qt.LeftButton) or (ev.buttons() & Qt.RightButton)):
            self.labelTheChar._painter.drawLine(self.labelTheChar._mouseLastX, self.labelTheChar._mouseLastY, ev.x(), ev.y())
        self.labelTheChar.endPaint()
    def on_mousePress(self,ev):
        self.labelTheChar.beginPaint()
        if (ev.buttons() & Qt.LeftButton):
            self.labelTheChar.setPen(QPen(QColor(255, 255, 255), float(self.spinBoxDrawWidth.text()), Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
            self.labelTheChar._painter.drawPoint(ev.x(), ev.y())
        elif (ev.buttons() & Qt.RightButton):
            self.labelTheChar.setPen(QPen(QColor(0, 0, 0), float(self.spinBoxDrawWidth.text()), Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin))
            self.labelTheChar._painter.drawPoint(ev.x(), ev.y())
        self.labelTheChar.endPaint()

app = QApplication(sys.argv)

myWidget = MyWidget()
labelTheChar = myWidget.labelTheChar
spinBoxDrawWidth = myWidget.spinBoxDrawWidth
labelTheChar.setPen(QPen(QBrush(QColor(255, 255, 255)), int(spinBoxDrawWidth.text()), Qt.SolidLine, Qt.RoundCap, Qt.RoundJoin));
QObject.connect(labelTheChar, SIGNAL('on_mouseMove'), myWidget.on_mouseMove)
QObject.connect(labelTheChar, SIGNAL('on_mousePress'), myWidget.on_mousePress)
spinBoxDrawWidth.setRange(1, 50)
spinBoxDrawWidth.setValue(5)
QObject.connect(myWidget.ui.pushButtonClearTheChar, SIGNAL('clicked()'), labelTheChar, SLOT('clear()'))

sys.exit(app.exec_())
MyPaintWidget.py
# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'F:\PythonProject\LearnProjects\TestProjects\MyPaintWidget.ui'
#
# Created by: PyQt4 UI code generator 4.11.4
#
# WARNING! All changes made in this file will be lost!

from PyQt4 import QtCore, QtGui

try:
    _fromUtf8 = QtCore.QString.fromUtf8
except AttributeError:
    def _fromUtf8(s):
        return s

try:
    _encoding = QtGui.QApplication.UnicodeUTF8
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig, _encoding)
except AttributeError:
    def _translate(context, text, disambig):
        return QtGui.QApplication.translate(context, text, disambig)

class Ui_MyPaintWidget(object):
    def setupUi(self, MyPaintWidget):
        MyPaintWidget.setObjectName(_fromUtf8("MyPaintWidget"))
        MyPaintWidget.resize(201, 221)
        self.pushButtonClearTheChar = QtGui.QPushButton(MyPaintWidget)
        self.pushButtonClearTheChar.setGeometry(QtCore.QRect(10, 190, 91, 23))
        self.pushButtonClearTheChar.setObjectName(_fromUtf8("pushButtonClearTheChar"))
        self.spinBoxDrawWidth = QtGui.QSpinBox(MyPaintWidget)
        self.spinBoxDrawWidth.setGeometry(QtCore.QRect(70, 0, 42, 16))
        self.spinBoxDrawWidth.setObjectName(_fromUtf8("spinBoxDrawWidth"))
        self.labelTheChar = MyLabel(MyPaintWidget)
        self.labelTheChar.setGeometry(QtCore.QRect(10, 20, 181, 161))
        palette = QtGui.QPalette()
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Active, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(255, 255, 255))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Inactive, QtGui.QPalette.Window, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Base, brush)
        brush = QtGui.QBrush(QtGui.QColor(0, 0, 0))
        brush.setStyle(QtCore.Qt.SolidPattern)
        palette.setBrush(QtGui.QPalette.Disabled, QtGui.QPalette.Window, brush)
        self.labelTheChar.setPalette(palette)
        self.labelTheChar.setAutoFillBackground(True)
        self.labelTheChar.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
        self.labelTheChar.setObjectName(_fromUtf8("labelTheChar"))
        self.labelDrawWidth = QtGui.QLabel(MyPaintWidget)
        self.labelDrawWidth.setGeometry(QtCore.QRect(10, 0, 61, 16))
        self.labelDrawWidth.setObjectName(_fromUtf8("labelDrawWidth"))

        self.retranslateUi(MyPaintWidget)
        QtCore.QMetaObject.connectSlotsByName(MyPaintWidget)

    def retranslateUi(self, MyPaintWidget):
        MyPaintWidget.setWindowTitle(_translate("MyPaintWidget", "画图", None))
        self.pushButtonClearTheChar.setText(_translate("MyPaintWidget", "Clear", None))
        self.labelTheChar.setText(_translate("MyPaintWidget", "TextLabel", None))
        self.labelDrawWidth.setText(_translate("MyPaintWidget", "画笔粗细:", None))

from MyLabel import MyLabel

if __name__ == "__main__":
    import sys
    app = QtGui.QApplication(sys.argv)
    MyPaintWidget = QtGui.QWidget()
    ui = Ui_MyPaintWidget()
    ui.setupUi(MyPaintWidget)
    MyPaintWidget.show()
    sys.exit(app.exec_())

古月河图 2016-05-10
  • 打赏
  • 举报
回复
谢谢你的回复,你的方法应该是对的,至少QWidget上面能够行得通,但是QScrollArea不行 我仔细看了下,貌似不在PaintDevice的列表之内。。。 我还有一个问题,假设我用PyQt4的将做好的.ui文件转换成了.py,并且成功运行出了图形界面 接下来我想在这个界面的某一个Widget上面绘图,按照网上的教程,通常的做法,就是自定义一个类,继承该widget,然后在它的paintEvent里面作图,这点和你告诉我的方法一样。 可是现在的问题是,因为通过pyuic转换过来的Qt配置文件是独立存在的,只要重新转换,在上面的任何改动都会消失,所以从这个意义上来讲,我不可能对它进行改动,而在这个文件当中,我所需要绘图的widget已经有了一个instance了,那么我在另外一个文件中自定义的类,怎样才能和这个已经存在的instance产生联系呢? 或者说,就算我自定义好一个子类,怎么使用才能使paintEvent()生效呢?
dianyancao 2016-05-10
  • 打赏
  • 举报
回复
试试继承QScrollArea得到子类,并重新定义其paintEvent在其中实现绘图 然后创建子类来绘图

37,719

社区成员

发帖
与我相关
我的任务
社区描述
JavaScript,VBScript,AngleScript,ActionScript,Shell,Perl,Ruby,Lua,Tcl,Scala,MaxScript 等脚本语言交流。
社区管理员
  • 脚本语言(Perl/Python)社区
  • IT.BOB
加入社区
  • 近7日
  • 近30日
  • 至今

试试用AI创作助手写篇文章吧