How to use this rewritten QLabel class in pyqt5? - pyqt5

I rewritten the OLabel class naming roiLabel(), and I want to get the ROI in a frame to tracking object.
class roiLabel(QLabel): # use roiLabel class to draw ROI
def __init__(self):
super().__init__()
self.open_keyboard_flag = False
self.open_mouse_flag = False
self.draw_roi_flag = False
self.select_roi_flag = False
self.clear_flag = False
self.x0 = 0
self.y0 = 0
self.x1 = 0
self.y1 = 0
self.rect = QRect()
self.label_show = None
# when clicking mouse, record the top left corner position.
def mousePressEvent(self, event: QMouseEvent):
if event.buttons() == Qt.LeftButton:
if self.open_mouse_flag is True:
self.select_roi_flag = True
self.x0 = event.x()
self.y0 = event.y()
# release the mouse
def mouseReleaseEvent(self, event):
self.select_roi_flag = False
And I instantiate this class to the self.show_windows = roiLabel().
I have the question that how to call the function mousePressEvent():
def mousePressEvent(self, event: QMouseEvent):
if event.buttons() == Qt.LeftButton:
if self.open_mouse_flag is True:
self.select_roi_flag = True
self.x0 = event.x()
self.y0 = event.y()
what should I fill this in (?):
self.show_windows = roiLabel()
self.show_windows.mousePressEvent(?)
I have no idea how to fill using self and event: QMouseEvent two arguments....
Thanks in advance!

Related

How to open context menu for an object that is empty, but has a size?

I am creating a GUI for a dependency graphing software... And am not able to figure out how to get a context menu to open for my lines.
What I want to do, right click on/near a MyLine widget and open a context menu... What is happening right clicks are not detected.
It is currently not detecting right clicks on the line widgets location to open a context menu (Purpose of this is to allow the user to delete/edit lines by right clicking on them).
What am I doing wrong here?
class MyLine(QWidget):
def __init__(self, destination: Node, source: Node, parent=None):
super().__init__(parent)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.showMenu)
self.destination = destination
self.source = source
self.setAutoFillBackground(True)
p = self.palette()
p.setColor(self.backgroundRole(), Qt.red)
self.setPalette(p)
def update_line_size(self):
origin = self.source.get_line_draw_pos(self.destination.pos())
destination = self.destination.get_line_draw_pos(self.source.pos())
leftcornerX = origin.x() if origin.x() < destination.x() else destination.x()
leftcornerY = origin.y() if origin.y() < destination.y() else destination.y()
sizeX = abs(origin.x() - destination.x())
sizeY = abs(origin.y() - destination.y())
self.setGeometry(leftcornerX, leftcornerY, sizeX, sizeY)
def showMenu(self, _):
menu = QMenu()
menu.addAction("Delete", self.remove)
menu.exec_(self.cursor().pos())
def draw(self, painter: QPainter):
origin = self.source.get_line_draw_pos(self.destination.pos())
destination = self.destination.get_line_draw_pos(self.source.pos())
painter.drawLine(origin, destination)
# DRAW ARROW HEAD
ARROW_SIZE = 10 # Might change
line_angle = calculate_line_angle(destination, origin)
draw_arrow_head(destination, painter, line_angle, ARROW_SIZE)
def remove(self):
self.parent().delete_line(self)
self.deleteLater()
Edit:
required types for reproducibility
class Node(QLabel):
def __init__(self, text: str, parent=None):
super().__init__(text, parent)
self.setContextMenuPolicy(Qt.CustomContextMenu)
self.customContextMenuRequested.connect(self.showMenu)
def get_line_draw_pos(self, other_side: QPoint):
x = self.pos().x() if other_side.x() < self.pos().x() else (self.pos().x() + self.width())
y = self.pos().y() if other_side.y() < self.pos().y() else (self.pos().y() + self.height())
return QPoint(x, y)
def showMenu(self, _):
pass #purposefully left as a stub
def calculate_line_angle(destination: QPoint, origin: QPoint):
return math.atan2(destination.y() - origin.y(), destination.x() - origin.x())
def draw_arrow_head(destination: QPoint, painter: QPainter, line_angle: float, arrow_size: float = 10):
angle1 = math.radians(22.5) + line_angle
angle2 = math.radians(-22.5) + line_angle
arrow1 = QPoint( int(destination.x() - arrow_size * math.cos(angle1)), int(destination.y() - arrow_size * math.sin(angle1)))
arrow2 = QPoint( int(destination.x() - arrow_size * math.cos(angle2)), int(destination.y() - arrow_size * math.sin(angle2)))
painter.drawLine(destination, arrow1)
painter.drawLine(destination, arrow2)
class MainWindow(QWidget):
def __init__(self):
super().__init__()
self.setAcceptDrops(True) # add a drop rule
self.setMouseTracking(True)
self.track_origin = None
self.track_mouse = QPoint(0,0)
self.lines = []
def paintEvent(self, event):
painter = QPainter(self)
for line in self.lines:
line.draw(painter)
line.update_line_size()
def connectNodes(self, destination: Node, source: Node):
self.lines.append(MyLine(destination, source))
self.update()
def delete_line(self, line: MyLine):
self.lines.remove(line)
self.update()
app = QApplication([])
window = MainWindow()
window.setWindowTitle("Right Click to remove label")
window.setGeometry(100, 100, 400, 200)
window.move(60,15)
nodes = []
for index, node_name in enumerate(["hello.txt", "not_a_villain.txt", "nope.txt"]):
node = Node(node_name, window)
node.move(50 + index*100, 50 + (index%2) * 50)
nodes.append(node)
window.connectNodes(nodes[0], nodes[1])
window.connectNodes(nodes[0], nodes[2])
window.connectNodes(nodes[1], nodes[2])
window.show()
sys.exit(app.exec_())

Rewritten QLabel class seems wrong in PyQt5

I rewrite the QLabel class to select ROI on the QLabel, aimed to acheive the cv2.selectROI function. But still wrong......
This is the code:
The QMainWindows Code:
class MyGui(QMainWindow):
def __init__(self, parent=None):
super(MyGui, self).__init__(parent)
self.init_rect = [0, 0, 0, 0]
self.tracker = None
self.first_frame = True
self.video_name = r'G:\dataset\example_Trim.mp4'
self.setupUi()
self.cap = None
self.status = self.statusBar() # 实例化创建状态栏
self.status.showMessage('Author', 10000) # 显示状态栏信息
self.timer_camera = QTimer()
self.show_windows = roiLabel()
self.show_windows.setFixedSize(1500, 800)
self.show_windows.move(50, 10)
self.show_windows.setStyleSheet("QLabel{background-color:gray;}")
def setupUi(self):
self.setObjectName("MainWindow")
self.setFixedSize(1600, 900) # 设置窗口的大小
self.setWindowFlag(QtCore.Qt.WindowMinimizeButtonHint) # 去掉最小化按钮
self.setWindowTitle('基于Transformer的视频目标跟踪方法研究') # 设置窗口标题
self.setWindowIcon(QIcon(r'F:\PythonDoc\trans_tt_backup\gui\pic\Windows_icon.png')) # 设置图标
self.move_center()
And the rewritten QLabel class is :
class roiLabel(QLabel): # 利用QLabel绘制ROI
def __init__(self):
super().__init__()
self.open_keyboard_flag = False
self.open_mouse_flag = False
self.draw_roi_flag = False
self.select_roi_flag = False
self.clear_flag = False
self.x0 = 0
self.y0 = 0
self.x1 = 0
self.y1 = 0
self.rect = QRect()
self.label_show = None
# 按下鼠标时,记录左上角坐标
def mousePressEvent(self, event):
if self.open_mouse_flag is True:
self.select_roi_flag = True
self.x0 = event.x()
self.y0 = event.y()
The problem is:
I want the 'python' windows is embed in mainwindows

Synchronize two QGraphicsView with different images

I would like to show two images next to each other, such that when I zoom or pan on one image the other image follows along. My current approach is to emit a viewUpdated event after resolving mouse events. The event contains the viewportTransformation and is used to update the transform in the other view. This sort of works for the zoom part, but panning does not work.
The code below is based on the qt5 version provided in this answer: https://stackoverflow.com/a/35514531/185475
from PyQt5 import QtCore, QtGui, QtWidgets
# Code from https://stackoverflow.com/a/35514531
class PhotoViewer(QtWidgets.QGraphicsView):
photoClicked = QtCore.pyqtSignal(QtCore.QPoint)
viewUpdated = QtCore.pyqtSignal(QtGui.QTransform)
def __init__(self, parent):
super(PhotoViewer, self).__init__(parent)
self._zoom = 0
self._empty = True
self._scene = QtWidgets.QGraphicsScene(self)
self._photo = QtWidgets.QGraphicsPixmapItem()
self._scene.addItem(self._photo)
self.setScene(self._scene)
self.setTransformationAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setResizeAnchor(QtWidgets.QGraphicsView.AnchorUnderMouse)
self.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
self.setBackgroundBrush(QtGui.QBrush(QtGui.QColor(30, 30, 30)))
self.setFrameShape(QtWidgets.QFrame.NoFrame)
def hasPhoto(self):
return not self._empty
def fitInView(self, scale=True):
rect = QtCore.QRectF(self._photo.pixmap().rect())
if not rect.isNull():
self.setSceneRect(rect)
if self.hasPhoto():
unity = self.transform().mapRect(QtCore.QRectF(0, 0, 1, 1))
self.scale(1 / unity.width(), 1 / unity.height())
viewrect = self.viewport().rect()
scenerect = self.transform().mapRect(rect)
factor = min(viewrect.width() / scenerect.width(),
viewrect.height() / scenerect.height())
self.scale(factor, factor)
self._zoom = 0
def setPhoto(self, pixmap=None):
self._zoom = 0
if pixmap and not pixmap.isNull():
self._empty = False
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
self._photo.setPixmap(pixmap)
else:
self._empty = True
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
self._photo.setPixmap(QtGui.QPixmap())
self.fitInView()
def wheelEvent(self, event):
if self.hasPhoto():
if event.angleDelta().y() > 0:
factor = 1.25
self._zoom += 1
else:
factor = 0.8
self._zoom -= 1
if self._zoom > 0:
self.scale(factor, factor)
elif self._zoom == 0:
self.fitInView()
else:
self._zoom = 0
self.viewUpdated.emit(self.viewportTransform())
def toggleDragMode(self):
if self.dragMode() == QtWidgets.QGraphicsView.ScrollHandDrag:
self.setDragMode(QtWidgets.QGraphicsView.NoDrag)
elif not self._photo.pixmap().isNull():
self.setDragMode(QtWidgets.QGraphicsView.ScrollHandDrag)
def mousePressEvent(self, event):
if self._photo.isUnderMouse():
self.photoClicked.emit(self.mapToScene(event.pos()).toPoint())
super(PhotoViewer, self).mousePressEvent(event)
self.viewUpdated.emit(self.viewportTransform())
def set_transform(self, transform):
self.setTransform(transform)
class Window(QtWidgets.QWidget):
def __init__(self):
super(Window, self).__init__()
self.viewer = PhotoViewer(self)
self.viewerSecondImage = PhotoViewer(self)
self.viewer.viewUpdated.connect(self.viewerSecondImage.set_transform)
self.viewerSecondImage.viewUpdated.connect(self.viewer.set_transform)
# 'Load image' button
self.btnLoad = QtWidgets.QToolButton(self)
self.btnLoad.setText('Load image')
self.btnLoad.clicked.connect(self.loadImage)
# Button to change from drag/pan to getting pixel info
self.btnPixInfo = QtWidgets.QToolButton(self)
self.btnPixInfo.setText('Enter pixel info mode')
self.btnPixInfo.clicked.connect(self.pixInfo)
self.editPixInfo = QtWidgets.QLineEdit(self)
self.editPixInfo.setReadOnly(True)
self.viewer.photoClicked.connect(self.photoClicked)
# Arrange layout
VBlayout = QtWidgets.QVBoxLayout(self)
HBlayoutImageViewers = QtWidgets.QHBoxLayout()
HBlayoutImageViewers.addWidget(self.viewer)
HBlayoutImageViewers.addWidget(self.viewerSecondImage)
VBlayout.addLayout(HBlayoutImageViewers)
HBlayout = QtWidgets.QHBoxLayout()
HBlayout.setAlignment(QtCore.Qt.AlignLeft)
HBlayout.addWidget(self.btnLoad)
HBlayout.addWidget(self.btnPixInfo)
HBlayout.addWidget(self.editPixInfo)
VBlayout.addLayout(HBlayout)
def loadImage(self):
self.viewer.setPhoto(QtGui.QPixmap('input/490px-Dostojka_adype.jpg'))
self.viewerSecondImage.setPhoto(QtGui.QPixmap('input/490px-Dostojka_adype.jpg'))
def pixInfo(self):
self.viewer.toggleDragMode()
def photoClicked(self, pos):
if self.viewer.dragMode() == QtWidgets.QGraphicsView.NoDrag:
self.editPixInfo.setText('%d, %d' % (pos.x(), pos.y()))
if __name__ == '__main__':
import sys
app = QtWidgets.QApplication(sys.argv)
window = Window()
window.setGeometry(500, 300, 800, 600)
window.show()
sys.exit(app.exec_())
You only need to syncronize scrollbar values of two QGraphicsViews
def bindScrollBars(scrollBar1, scrollBar2):
# syncronizing scrollbars syncrnonously somehow breaks zooming and doesn't work
# scrollBar1.valueChanged.connect(lambda value: scrollBar2.setValue(value))
# scrollBar2.valueChanged.connect(lambda value: scrollBar1.setValue(value))
# syncronizing scrollbars asyncronously works ok
scrollBar1.valueChanged.connect(lambda _: QtCore.QTimer.singleShot(0, lambda: scrollBar2.setValue(scrollBar1.value())))
scrollBar2.valueChanged.connect(lambda _: QtCore.QTimer.singleShot(0, lambda: scrollBar1.setValue(scrollBar2.value())))
class Window(QtWidgets.QWidget):
def __init__(self):
...
bindScrollBars(self.viewer.horizontalScrollBar(), self.viewerSecondImage.horizontalScrollBar())
bindScrollBars(self.viewer.verticalScrollBar(), self.viewerSecondImage.verticalScrollBar())
Also wheelEvent can be simplified
def wheelEvent(self, event):
if self.hasPhoto():
factor = 1.25
if event.angleDelta().y() > 0:
self.scale(factor, factor)
else:
self.scale(1/factor, 1/factor)
self.viewUpdated.emit(self.transform())

how to make copy paste to follow the same pattern

I am creating a design with my QGraphicsitems . I have selected all the items in the scene and pasted it.But it is not following the same pattern.can we make the items paste in the same pattern like the one which we have created initially? –
I have tried with the following code
from PyQt5.QtCore import (QByteArray,QDataStream, QIODevice,pyqtSlot, QMimeData, QPointF, QPoint, Qt, QRect,QTimer,QLineF, QEvent,QRectF)
from PyQt5.QtGui import QColor,QDrag, QPainter, QPixmap,QFont,QFontMetrics,QBrush, QLinearGradient, QIcon, QPen, QPainterPath, QTransform,QCursor,QMouseEvent,QClipboard
from PyQt5.QtWidgets import QApplication,QGraphicsTextItem,QGraphicsItemGroup, QSizePolicy,QShortcut, QScrollArea, QPushButton,QLineEdit, QMainWindow,QInputDialog, QGraphicsPathItem,QDialog, QVBoxLayout,QGraphicsItem,QStatusBar,QTextEdit, QAction,QMenu, qApp,QSplitter, QButtonGroup, QToolButton, QFrame, QHBoxLayout, QGraphicsView, QGraphicsItem, QGraphicsPixmapItem, QLabel, QGraphicsScene, QWidget
import importlib
import SketchBook as sketchBook
import Blocks as blocks
import random
custom_mimeType = "application/x-qgraphicsitems"
pos1 = QPointF()
def item_to_ds(it, ds):
if not isinstance(it, QGraphicsItem):
return
ds.writeQString(it.__class__.__module__)
ds.writeQString(it.__class__.__name__)
ds.writeInt(it.flags())
ds << it.pos()
posdiff = it.pos().x() -pos1().x()
pos1 = QPointF(it.pos().x(),it.pos().y())
# ds.writeInt(it.UserType)
ds.writeFloat(it.opacity())
ds.writeFloat(it.rotation())
ds.writeFloat(it.scale())
# ds.writeString(it.type())
# ds.writeQString(it.type1())
# if isinstance(it, QGraphicsItem):
# ds << it.brush() << it.pen()
if isinstance(it, QGraphicsPixmapItem):
ds << it.pixmap()
if isinstance(it, QGraphicsPathItem):
ds << it.path()
def ds_to_item(ds):
module_name = ds.readQString()
class_name = ds.readQString()
if class_name == 'QGraphicsPixmapItem':
mod = importlib.import_module(module_name)
it = getattr(mod, class_name)()
# flags = QGraphicsItem.GraphicsItemFlag(ds.readInt())
# pos = QPointF()
# ds >> pos
# it.setFlags(flags)
# it.setPos(pos)
# it.setOpacity(ds.readFloat())
# it.setRotation(ds.readFloat())
# it.setScale(ds.readFloat())
else:
mod = importlib.import_module(module_name)
it = getattr(mod, class_name)(blocks.selectedObjType)
flags = QGraphicsItem.GraphicsItemFlag(ds.readInt())
pos = QPointF()
ds >> pos
it.setFlags(flags)
it.setPos(pos)
it.setOpacity(ds.readFloat())
it.setRotation(ds.readFloat())
it.setScale(ds.readFloat())
# if isinstance(it, QGraphicsItem):
# pen, brush = QPen(), QBrush()
# ds >> brush
# ds >> pen
# it.setPen(pen)
# it.setBrush(brush)
if isinstance(it, QGraphicsPathItem):
path = QPainterPath()
ds >> path
it.setPath(path)
if isinstance(it, QGraphicsPixmapItem):
pixmap = QPixmap()
# pen, brush = QPen(), QBrush()
# ds >> brush
# ds >> pen
ds >> pixmap
it.setPixmap(pixmap)
return it
class GraphicsSceneClass(QGraphicsScene):
global selectedObjType
def __init__(self, parent=None):
super(GraphicsSceneClass, self).__init__(parent)
self.gridOn = 0
self.setSceneRect(0, 0, 1920, 1080)
self.setItemIndexMethod(QGraphicsScene.NoIndex)
self.setBackgroundBrush(QBrush(Qt.black))
def mousePressEvent(self, event):
sampleTransform = QTransform()
objectAtMouse = self.itemAt(event.scenePos(), sampleTransform)
if objectAtMouse and event.button()== Qt.LeftButton:
objectAtMouse.setSelected(True)
elif objectAtMouse==None and event.button()==Qt.RightButton:
# pass
self.grid = self.TargPosForLine(event.scenePos(), "ForLine")
self.grid = self.TargPosForLine(event.scenePos(), "ForLine")
print(self.grid)
# else:
# self.DeselectItems()
# objectAtMouse.QShortcut
def TargPosForLine(self, position, mode):
clicked_column = int((position.y() // 16)) * 16
clicked_row = int((position.x() // 16)) * 16
if clicked_column < 0:
clicked_column = 0
if clicked_row < 0:
clicked_row = 0
if(mode == "ForRect"):
return QRect(clicked_row, clicked_column,16,16)
elif(mode == "ForLine"):
return QPointF(clicked_row,clicked_column)
def DeselectItems(self):
selectedObjects = self.selectedItems()
for object in selectedObjects:
object.setSelected(False)
def mouseReleaseEvent(self, event):
# self.DeselectItems()
pass
class MainWindow(QMainWindow):
global selectedObjType
# global item
def __init__(self,):
super(MainWindow, self).__init__()
self.createActions()
self.createMenus()
self.createToolbars()
self.scene = GraphicsSceneClass()
MainWindow.obj = self.scene
self.view = QGraphicsView(self.scene)
# self.view.setDragMode(QGraphicsView.RubberBandDrag)
self.view.setMouseTracking(True)
self.view.setRenderHint(QPainter.HighQualityAntialiasing)
self.widg = QWidget()
self.horizontalLayout = QHBoxLayout()
self.horizontalLayout.addWidget(self.view)
self.widg.setMouseTracking(True)
self.widget = QWidget()
self.widget.setLayout(self.horizontalLayout)
self.setCentralWidget(self.widget)
self.obj=None
def createMenus(self):
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.exitAction)
fileMenu = menuBar.addMenu('&Edit')
fileMenu.addAction(self.copyAction)
fileMenu.addAction(self.pasteAction)
fileMenu.addAction(self.selectAction)
def createActions(self):
self.exitAction = QAction("E&xit", self, shortcut="Ctrl+X", statusTip="Quit Scenediagram example",
triggered=self.deleteItem)
self.copyAction = QAction("C&opy", self, shortcut="Ctrl+C", triggered=self.copy)
self.pasteAction = QAction("P&aste", self, shortcut="Ctrl+V", triggered=self.paste)
self.selectAction = QAction("S&electAll", self, shortcut="Ctrl+A", triggered=self.selectAll)
def createToolbars(self):
GridButton = QToolButton()
GridButton.setCheckable(True)
GridButton.setIcon(QIcon('images/GridButton.png'))
GridButton.clicked.connect(self.GridOnOffControl)
GridButton.setToolTip("Grid Control")
self.pointerToolbar = self.addToolBar("Pointer type")
self.pointerToolbar.addWidget(GridButton)
def deleteItem(self):
for item in self.scene.selectedItems():
self.scene.removeItem(item)
def selectAll(self):
for item in self.scene.items():
item.setSelected(True)
def GridOnOffControl(self):
if self.scene.gridOn == 0:
self.scene.gridOn = 1
else:
self.scene.gridOn = 0
if self.scene.gridOn == 1:
self.scene.setBackgroundBrush(QBrush(QPixmap('images/Grid.png')))
else:
self.scene.setBackgroundBrush(QBrush(Qt.black))
def contextMenuEvent(self, event):
contextMenu = QMenu(self)
Cutaction = contextMenu.addAction("Cut")
Coaction = contextMenu.addAction("Copy")
Paaction = contextMenu.addAction("Paste")
Propaction = contextMenu.addAction("draw1")
Propaction1=contextMenu.addAction("draw2")
quitAct = contextMenu.addAction("quit")
action = contextMenu.exec_(self.mapToGlobal(event.pos()))
if action == quitAct:
self.close()
elif action == Propaction:
objectDrop = None
# painterPath = QPainterPath()
#
# painterPath.moveTo(10, 50.0)
# painterPath.lineTo(50,50)
# painterPath.lineTo(50,55)
# painterPath.lineTo(10,55)
# gradient = QLinearGradient(1, 1, 1, 5)
# gradient.setColorAt(0, QColor(Qt.gray))
# gradient.setColorAt(0.5, QColor(192, 192, 192, 255))
# gradient.setColorAt(1, QColor(Qt.darkGray))
# painterPath.closeSubpath()
#
# objectDrop = QGraphicsPathItem()
# objectDrop.setPath(painterPath)
# objectDrop.setBrush(QBrush(gradient))
objectDrop = QGraphicsPixmapItem(QPixmap("2AS_HG_RG.png"))
objectDrop.setPos(self.scene.grid)
print("sig",self.scene.grid)
# objectDrop._position = QPointF(gridPos.x() + 2, gridPos.y() + 5.9)
# objectDrop._type = "2AS_HG_RG"
objectDrop._type1 = "2AS_HG_RG"
self.scene.addItem(objectDrop)
objectDrop.setFlag(QGraphicsItem.ItemIsSelectable)
objectDrop.setFlag(QGraphicsItem.ItemIsMovable)
objectDrop._type1="2AS_HG_RG"
# self.scene.addPath(painterPath)
elif action==Propaction1:
objectDrop = None
selectedObjType = "line"
objectDrop = sketchBook.SketchBook(selectedObjType)
print("line",self.scene.grid)
objectDrop.setFlag(QGraphicsItem.ItemIsSelectable)
objectDrop.setFlag(QGraphicsItem.ItemIsMovable)
objectDrop._type1 = "line"
objectDrop.setPos(self.scene.grid.x(),self.scene.grid.y()-48+5)
self.scene.addItem(objectDrop)
elif action == Coaction:
self.copy()
elif action == Paaction:
self.paste()
#pyqtSlot()
def copy(self):
mimedata = QMimeData()
ba = QByteArray()
ds = QDataStream(ba, QIODevice.WriteOnly)
for it in self.scene.selectedItems():
self.posdiff=item_to_ds(it, ds)
mimedata.setData(custom_mimeType, ba)
clipboard = QApplication.clipboard()
clipboard.setMimeData(mimedata)
#pyqtSlot()
def paste(self):
pos2=self.scene.grid
clipboard = QApplication.clipboard()
mimedata = clipboard.mimeData()
if mimedata.hasFormat(custom_mimeType):
ba = mimedata.data(custom_mimeType)
# STR = str(ba)
# QW = ba.capacity()
ds = QDataStream(ba)
while not ds.atEnd():
# for it in ds:
it = ds_to_item(ds)
if isinstance(it, QGraphicsPixmapItem):
self.scene.addItem(it)
it.setPos(pos2)
it._position = QPointF(pos2.x() + 2, pos2.y() + 5.9)
print("sig",it._position)
it._type1 = "2AS_HG_RG"
else:
gradient = QLinearGradient(1, 1, 1, 5)
gradient.setColorAt(0, QColor(Qt.gray))
gradient.setColorAt(0.5, QColor(192, 192, 192, 255))
gradient.setColorAt(1, QColor(Qt.darkGray))
self.scene.addItem(it)
it.setBrush(QBrush(gradient))
it.setPos(pos2.x()+self.posdiff().x(),pos2.y()-48)
it._position = QPointF(pos2.x() + 2, pos2.y() + 5.9)
print(it._position)
# it.setFlags(QGraphicsItem.ItemIsSelectable)
# it._type1 = "line"
def selectedItem(self):
items = self.scene.selectedItems()
if len(items) == 1:
return items[0]
return None
if __name__=="__main__":
import sys
app=QApplication(sys.argv)
mainWindow = MainWindow()
mainWindow.show()
sys.exit(app.exec_())
1) select all the items or the items to be pasted
2) copy it
3) paste it
if we have design pattern have item1 followed by item2 followed by item3 with respective distance. When we copy and paste it it should follow the same pattern.
QGraphicsItem.setPos() is absolute to the scene (or relative to its parent), the alternative solution is to use moveBy(x, y) (which is the same as setPos(self.pos() + deltaPos), but you have to take into account the relative position of the click according to the reference point.
I'd suggest you to not set the position until all items have been added, and then set their position according to a specific item that will be used as an "anchor" point.
#pyqtSlot()
def paste(self):
pos2=self.scene.grid
clipboard = QApplication.clipboard()
mimedata = clipboard.mimeData()
items = []
topLeft = None
if mimedata.hasFormat(custom_mimeType):
ba = mimedata.data(custom_mimeType)
ds = QDataStream(ba)
while not ds.atEnd():
it = ds_to_item(ds)
items.append(it)
if not topLeft:
topLeft = it
elif it.y() < topLeft.y() or it.x() < topLeft.x():
# find a possible topmost/leftmost item
topLeft = it
# add items, but do not set their position here
# ...
delta = self.scene.grid - topLeft.pos()
[i.moveBy(delta.x(), delta.y()) for i in items]
An alternative is to find the "anchor" in the copy procedure, and set the position of each item relative to that point in the datastream, so that you'll be able to use moveBy(pos2.x(), pos2.y()) directly after adding the items.

Double buffering in Jython

recently I started learning Jython and now I have rather simply problem. I would like to improve quality of my animation. Unfortunately I don't know how to add double buffering to my applet . Could you help me?
Best regards!
from javax.swing import JToolBar
from javax.swing import JButton
from javax.swing import JFrame
import time
from java import awt
from java.awt import BorderLayout
class Canvas(awt.Canvas):
u"Canvas - drawing area"
def __init__(self,winSize = 400):
self.play = False
self.background=awt.Color.black
self.winSize = winSize
self.l = 0
def playSim(self, play):
if play == True:
self.play = True
self.repaint()
else: self.play = False
def paint(self, g):
g.fillRect(50, int(self.winSize/4), self.l, int(self.winSize/2))
if self.l < self.winSize: self.l += 1
else: self.l = 0
time.sleep(0.02)
if self.play == True: self.repaint()
class Example(JFrame):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
winSize = 600
toolbar = JToolBar()
self.playButton = JButton("Start", actionPerformed=self.playButtonPress )
toolbar.add(self.playButton)
self.add(toolbar, BorderLayout.NORTH)
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
self.setSize(winSize, winSize)
self.setResizable(False)
self.setLocationRelativeTo(None)
self.setVisible(True)
self.canvas = Canvas(winSize)
self.getContentPane().add(self.canvas)
self.setTitle("TEST")
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
def playButtonPress(self, e):
if self.playButton.getLabel() == "Start":
self.canvas.playSim(True)
self.playButton.setLabel("Stop")
else:
self.playButton.setLabel("Start")
self.canvas.playSim(False)
if __name__ == '__main__':
Example()
I solved my recent problem:
from javax.swing import JToolBar
from javax.swing import JButton
from javax.swing import JFrame
import time
from java import awt
from java.awt import BorderLayout
class Canvas(awt.Canvas):
u"Canvas - drawing area"
def __init__(self,winSize = 400):
self.play = False
self.background=awt.Color.black
self.winSize = winSize
self.l = 0
self.bi = BufferedImage(winSize, winSize, BufferedImage.TYPE_INT_RGB)
self.offScreenGraphics = self.bi.getGraphics()
def playSim(self, play):
if play == True:
self.play = True
self.repaint()
else: self.play = False
def paint(self, g):
self.offScreenGraphics.fillRect(50, int(self.winSize/4), self.l, int(self.winSize/2))
if self.l < self.winSize: self.l += 1
else: self.l = 0
g.drawImage(self.bi, 0, 0, None)
time.sleep(0.02)
if self.play == True: self.repaint()
class Example(JFrame):
def __init__(self):
super(Example, self).__init__()
self.initUI()
def initUI(self):
winSize = 600
toolbar = JToolBar()
self.playButton = JButton("Start", actionPerformed=self.playButtonPress )
toolbar.add(self.playButton)
self.add(toolbar, BorderLayout.NORTH)
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
self.setSize(winSize, winSize)
self.setResizable(False)
self.setLocationRelativeTo(None)
self.setVisible(True)
self.canvas = Canvas(winSize)
self.getContentPane().add(self.canvas)
self.setTitle("TEST")
self.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
def playButtonPress(self, e):
if self.playButton.getLabel() == "Start":
self.canvas.playSim(True)
self.playButton.setLabel("Stop")
else:
self.playButton.setLabel("Start")
self.canvas.playSim(False)
if __name__ == '__main__':
Example()
Now I've another(rather trivial) problem:
How can I make from this python file *the class file* which would be ready to publish it on website as an applet?