Уведомления

Группа в Telegram: @pythonsu

#1 Янв. 23, 2009 11:59:24

ice
От:
Зарегистрирован: 2008-01-12
Сообщения: 156
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQT4 рисование.

Доброго времени суток.

Просто для саморазвития:

Рисую на виджете. Просто линии, фигуры и тд.

А вот как бы сделать динамический объект рисования? то есть хочу нарисовать линию, тыкаю мышой, веду мышь и линия протягивается от точки начала до мыши, отпускаю мышь и линия остается на рисунке (в общем-то как в любой рисовалке “линия”). То есть где-то надо запомнить предыдущий рисунок, чтоб поверх него “водить” линию.

Все вопрос решен. Просто делаю новый QtGui.QImage() при нажатии на кнопку мыши, а в репаинте восстанавливаю его и рисую поверх.



Отредактировано (Янв. 26, 2009 13:48:22)

Офлайн

#2 Фев. 1, 2009 22:01:20

wonderfulll
От:
Зарегистрирован: 2009-01-30
Сообщения: 72
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQT4 рисование.

Напоследок стандартный пример который идёт с документацией.

#!/usr/bin/env python

############################################################################*
##
## Copyright (C) 2005-2005 Trolltech AS. All rights reserved.
##
## This file is part of the example classes of the Qt Toolkit.
##
## This file may be used under the terms of the GNU General Public
## License version 2.0 as published by the Free Software Foundation
## and appearing in the file LICENSE.GPL included in the packaging of
## this file. Please review the following information to ensure GNU
## General Public Licensing requirements will be met:
## http://www.trolltech.com/products/qt/opensource.html
##
## If you are unsure which license is appropriate for your use, please
## review the following information:
## http://www.trolltech.com/products/qt/licensing.html or contact the
## sales department at sales@trolltech.com.
##
## This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
## WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
##
############################################################################/

import sys
from PyQt4 import QtCore, QtGui


class ScribbleArea(QtGui.QWidget):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)

self.setAttribute(QtCore.Qt.WA_StaticContents)
self.modified = False
self.scribbling = False
self.myPenWidth = 1
self.myPenColor = QtCore.Qt.blue
self.image = QtGui.QImage()
self.lastPoint = QtCore.QPoint()

def openImage(self, fileName):
loadedImage = QtGui.QImage()
if not loadedImage.load(fileName):
return False

newSize = loadedImage.size().expandedTo(size())
self.resizeImage(loadedImage, newSize)
self.image = loadedImage
self.modified = False
self.update()
return True

def saveImage(self, fileName, fileFormat):
visibleImage = self.image
self.resizeImage(visibleImage, size())

if visibleImage.save(fileName, fileFormat):
self.modified = False
return True
else:
return False

def setPenColor(self, newColor):
self.myPenColor = newColor

def setPenWidth(self, newWidth):
self.myPenWidth = newWidth

def clearImage(self):
self.image.fill(QtGui.qRgb(255, 255, 255))
self.modified = True
self.update()

def mousePressEvent(self, event):
if event.button() == QtCore.Qt.LeftButton:
self.lastPoint = event.pos()
self.scribbling = True

def mouseMoveEvent(self, event):
if (event.buttons() & QtCore.Qt.LeftButton) and self.scribbling:
self.drawLineTo(event.pos())

def mouseReleaseEvent(self, event):
if event.button() == QtCore.Qt.LeftButton and self.scribbling:
self.drawLineTo(event.pos())
self.scribbling = False

def paintEvent(self, event):
painter = QtGui.QPainter()
painter.begin(self)
painter.drawImage(QtCore.QPoint(0, 0), self.image)
painter.end()

def resizeEvent(self, event):
if self.width() > self.image.width() or self.height() > self.image.height():
newWidth = max(self.width() + 128, self.image.width())
newHeight = max(self.height() + 128, self.image.height())
self.resizeImage(self.image, QtCore.QSize(newWidth, newHeight))
self.update()

QtGui.QWidget.resizeEvent(self, event)

def drawLineTo(self, endPoint):
painter = QtGui.QPainter()
painter.begin(self.image)
painter.setPen(QtGui.QPen(self.myPenColor, self.myPenWidth,
QtCore.Qt.SolidLine, QtCore.Qt.RoundCap,
QtCore.Qt.RoundJoin))
painter.drawLine(self.lastPoint, endPoint)
painter.end()
self.modified = True

rad = self.myPenWidth / 2 + 2
self.update(QtCore.QRect(self.lastPoint, endPoint).normalized()
.adjusted(-rad, -rad, +rad, +rad))
self.lastPoint = QtCore.QPoint(endPoint)

def resizeImage(self, image, newSize):
if image.size() == newSize:
return

newImage = QtGui.QImage(newSize, QtGui.QImage.Format_RGB32)
newImage.fill(QtGui.qRgb(255, 255, 255))
painter = QtGui.QPainter()
painter.begin(newImage)
painter.drawImage(QtCore.QPoint(0, 0), image)
painter.end()
self.image = newImage

def isModified(self):
return self.modified

def penColor(self):
return self.myPenColor

def penWidth(self):
return self.myPenWidth


class MainWindow(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)

self.saveAsActs = []

self.scribbleArea = ScribbleArea()
self.setCentralWidget(self.scribbleArea)

self.createActions()
self.createMenus()

self.setWindowTitle(self.tr("Scribble"))
self.resize(500, 500)

def closeEvent(self, event):
if self.maybeSave():
event.accept()
else:
event.ignore()

def open(self):
if self.maybeSave():
fileName = QtGui.QFileDialog.getOpenFileName(self,
self.tr("Open File"),
QtCore.QDir.currentPath())
if not fileName.isEmpty():
self.scribbleArea.openImage(fileName)

def save(self):
action = self.sender()
fileFormat = action.data().toByteArray()
self.saveFile(fileFormat)

def penColor(self):
newColor = QtGui.QColorDialog.getColor(self.scribbleArea.penColor())
if newColor.isValid():
self.scribbleArea.setPenColor(newColor)

def penWidth(self):
newWidth, ok = QtGui.QInputDialog.getInteger(self, self.tr("Scribble"),
self.tr("Select pen width:"),
self.scribbleArea.penWidth(),
1, 50, 1)
if ok:
self.scribbleArea.setPenWidth(newWidth)

def about(self):
QtGui.QMessageBox.about(self, self.tr("About Scribble"), self.tr(
"<p>The <b>Scribble</b> example shows how to use QMainWindow as the "
"base widget for an application, and how to reimplement some of "
"QWidget's event handlers to receive the events generated for "
"the application's widgets:</p><p> We reimplement the mouse event "
"handlers to facilitate drawing, the paint event handler to "
"update the application and the resize event handler to optimize "
"the application's appearance. In addition we reimplement the "
"close event handler to intercept the close events before "
"terminating the application.</p><p> The example also demonstrates "
"how to use QPainter to draw an image in real time, as well as "
"to repaint widgets.</p>"))

def createActions(self):
self.openAct = QtGui.QAction(self.tr("&Open..."), self)
self.openAct.setShortcut(self.tr("Ctrl+O"))
self.connect(self.openAct, QtCore.SIGNAL("triggered()"), self.open)

for format in QtGui.QImageWriter.supportedImageFormats():
text = self.tr("%1...").arg(QtCore.QString(format).toUpper())

action = QtGui.QAction(text, self)
action.setData(QtCore.QVariant(format))
self.connect(action, QtCore.SIGNAL("triggered()"), self.save)
self.saveAsActs.append(action)

self.exitAct = QtGui.QAction(self.tr("E&xit"), self)
self.exitAct.setShortcut(self.tr("Ctrl+Q"))
self.connect(self.exitAct, QtCore.SIGNAL("triggered()"),
self, QtCore.SLOT("close()"))

self.penColorAct = QtGui.QAction(self.tr("&Pen Color..."), self)
self.connect(self.penColorAct, QtCore.SIGNAL("triggered()"),
self.penColor)

self.penWidthAct = QtGui.QAction(self.tr("Pen &Width..."), self)
self.connect(self.penWidthAct, QtCore.SIGNAL("triggered()"),
self.penWidth)

self.clearScreenAct = QtGui.QAction(self.tr("&Clear Screen"), self)
self.clearScreenAct.setShortcut(self.tr("Ctrl+L"))
self.connect(self.clearScreenAct, QtCore.SIGNAL("triggered()"),
self.scribbleArea.clearImage)

self.aboutAct = QtGui.QAction(self.tr("&About"), self)
self.connect(self.aboutAct, QtCore.SIGNAL("triggered()"), self.about)

self.aboutQtAct = QtGui.QAction(self.tr("About &Qt"), self)
self.connect(self.aboutQtAct, QtCore.SIGNAL("triggered()"),
QtGui.qApp, QtCore.SLOT("aboutQt()"))

def createMenus(self):
self.saveAsMenu = QtGui.QMenu(self.tr("&Save As"), self)
for action in self.saveAsActs:
self.saveAsMenu.addAction(action)

self.fileMenu = QtGui.QMenu(self.tr("&File"), self)
self.fileMenu.addAction(self.openAct)
self.fileMenu.addMenu(self.saveAsMenu)
self.fileMenu.addSeparator()
self.fileMenu.addAction(self.exitAct)

self.optionMenu = QtGui.QMenu(self.tr("&Options"), self)
self.optionMenu.addAction(self.penColorAct)
self.optionMenu.addAction(self.penWidthAct)
self.optionMenu.addSeparator()
self.optionMenu.addAction(self.clearScreenAct)

self.helpMenu = QtGui.QMenu(self.tr("&Help"), self)
self.helpMenu.addAction(self.aboutAct)
self.helpMenu.addAction(self.aboutQtAct)

self.menuBar().addMenu(self.fileMenu)
self.menuBar().addMenu(self.optionMenu)
self.menuBar().addMenu(self.helpMenu)

def maybeSave(self):
if self.scribbleArea.isModified():
ret = QtGui.QMessageBox.warning(self, self.tr("Scribble"),
self.tr("The image has been modified.\n"
"Do you want to save your changes?"),
QtGui.QMessageBox.Yes | QtGui.QMessageBox.Default,
QtGui.QMessageBox.No,
QtGui.QMessageBox.Cancel | QtGui.QMessageBox.Escape)
if ret == QtGui.QMessageBox.Yes:
return self.saveFile("png")
elif ret == QtGui.QMessageBox.Cancel:
return False

return True

def saveFile(self, fileFormat):
initialPath = QtCore.QDir.currentPath() + "/untitled." + fileFormat

fileName = QtGui.QFileDialog.getSaveFileName(self, self.tr("Save As"),
initialPath,
self.tr("%1 Files (*.%2);;All Files (*)")
.arg(QtCore.QString(fileFormat.toUpper()))
.arg(QtCore.QString(fileFormat)))
if fileName.isEmpty():
return False
else:
return self.scribbleArea.saveImage(fileName, fileFormat)


if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
window = MainWindow()
window.show()
sys.exit(app.exec_())



Офлайн

#3 Фев. 2, 2009 17:16:11

ice
От:
Зарегистрирован: 2008-01-12
Сообщения: 156
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQT4 рисование.

да, я этот пример и смотрел. Только я как бы имел ввиду, что мне не просто линию надо, мне нужно, чтоб она протягивалась от мыши и до точки начала (или наоборот, как хотите). то есть картинка не менялась пока я не отпущу кнопу мыши (простенький такой редактор SVG накидать надо было для саморазвития). Как раз пример Scribble и переделал.



Офлайн

#4 Май 31, 2009 17:24:39

Ardling
От:
Зарегистрирован: 2009-05-01
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQT4 рисование.

Здравствуйте. Скопировал приведенный выше код и запустил. Окно откылось, линии рисуются, а открыть картинку jpg не получилось, в чем может быть проблема? В моих программах, написанных по разным руководствам результат аналогичный - рисуеки не открываются. В чем может быть проблема?

Использую Gentoo, Python 2.5.4, PyQt4-4.4.4-r2



Офлайн

#5 Май 31, 2009 19:11:00

Ardling
От:
Зарегистрирован: 2009-05-01
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQT4 рисование.

Людииии, подскажите как нарисовать jpg картинку!!!



Офлайн

#6 Май 31, 2009 19:26:22

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

PyQT4 рисование.

Не хочу разбирать код выше, но сам только что рисовал…

# coding: utf-8

from PyQt4 import QtCore, QtGui

class DrawWidget(QtGui.QFrame):
def __init__(self, *args):
QtGui.QFrame.__init__(self, *args)
self.pixmap = QtGui.QPixmap()

def setPixmap(self, pixmap):
self.pixmap = pixmap
self.repaint()

def clear(self):
self.pixmap = QtGui.QPixmap()
self.repaint()

def paintEvent(self, event):
QtGui.QFrame.paintEvent(self, event)

if not self.pixmap.isNull():
painter = QtGui.QPainter(self)
if self.width()-4 <= self.pixmap.width() or \
self.height()-4 <= self.pixmap.height():
px = self.pixmap.scaled(self.width()-4, self.height()-4,
QtCore.Qt.KeepAspectRatio,
QtCore.Qt.SmoothTransformation)
else:
px = self.pixmap
x = (self.width() - px.width()) / 2
y = (self.height() - px.height()) / 2
painter.drawPixmap(x, y, px)
painter.end()
Ну и читай доку по QtGui.QPixmap.
Если не разбирёшься – ещё рано.



Офлайн

#7 Май 31, 2009 21:52:31

Ardling
От:
Зарегистрирован: 2009-05-01
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQT4 рисование.

А есть хорошая дока с примерами?



Офлайн

#8 Май 31, 2009 22:08:13

Ardling
От:
Зарегистрирован: 2009-05-01
Сообщения: 20
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQT4 рисование.

ZZZ Спсибо. В вашем коде я разобрался (если он действительно рисует изображение, масштабированное под размер окна), и оно навело меня на правильные мысли. В итоге сделал сам, через QLabel, но появились новые вопросы:
Я хочу выводить несколько картинок и иметь возможность их друг относительно друга перетаскивать, как это лучше сделать, через QLabel, QPainter или как-то еще?



Офлайн

#9 Май 31, 2009 22:33:37

poltergeist
От:
Зарегистрирован: 2007-02-28
Сообщения: 522
Репутация: +  0  -
Профиль   Отправить e-mail  

PyQT4 рисование.

Ardling
Я хочу выводить несколько картинок и иметь возможность их друг относительно друга перетаскивать, как это лучше сделать, через QLabel, QPainter или как-то еще?
Тут QGraphicsView будет уместен.



Офлайн

#10 Май 31, 2009 23:34:59

ZZZ
От: Москва
Зарегистрирован: 2008-04-03
Сообщения: 2161
Репутация: +  26  -
Профиль   Адрес электронной почты  

PyQT4 рисование.

Ardling
А есть хорошая дока с примерами?
Вот это вопрос! Конечно есть!

Ardling
если он действительно рисует изображение
Что значит это “если”??? :-))) Рисует! И ещё как! QLabel с его setPixmap меня совершенно не устраивал, поэтому “я построил свой лунный модуль”… И использую его посредствам Promoted widgets (спасибо за пинок poltergeist'у).



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version