pyqt drawing on an exsiting widget of GUI - python

I am new to pyqt. I am doing a program that allows you clicks on the picture and remember the coordinates of points you clicks and draw a stickfigure on a widget of the GUI. My code right now can prompt out a new window to show a polygon with 4 points. However, I hope it can be displayed on the ui file I alreay made by pyqt. The object name for the widget is called widget.I hope someone can help me to modify the code to display the polygon on the gui widget not prompting out a new window.
Thank you so much!!!
import sys
from PyQt4.QtCore import *
from PyQt4 import QtGui, QtCore
from PyQt4.QtGui import *
from Main_window import *
global imgloc
imgloc = "1.jpg"
array = []
clicks = 0
class MyForm(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.ui = Ui_MainWindow()
self.ui.setupUi(self)
self.local_image = QImage(imgloc)
self.imageLocation = imgloc
self.local_scene = QGraphicsScene()
self.pixMapItem = QGraphicsPixmapItem(QPixmap(self.local_image), None, self.local_scene)
self.ui.graphicsView_5.setScene( self.local_scene )
self.pixMapItem.mousePressEvent = self.pixelSelect
def pixelSelect(self,event):
global imgloc
a = event.pos().x()
b = event.pos().y()
global clicks
global array
if clicks != 4:
clicks += 1
point = QPoint(a,b)
array.append(point)
else:
clicks = 0
dialog = DialogBody()
dialog.show()
dialog.exec_()
array = []
class DialogBody(QDialog):
def __init__(self,parent=None):
super(QDialog,self).__init__(parent)
self.setGeometry(100, 100, QImage(imgloc).height(), QImage(imgloc).width())
def paintEvent(self,e):
qp = QtGui.QPainter()
qp.begin(self)
self.drawBody(qp)
qp.end()
def drawBody(self, qp):
qp.setPen(QtCore.Qt.red)
qp.drawPolygon(array[0],array[1],array[2],array[3])
qp.drawEllipse(array[0],2,2)
qp.drawEllipse(array[1],2,2)
qp.drawEllipse(array[2],2,2)
qp.drawEllipse(array[3],2,2)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
myapp= MyForm()
myapp.show()
sys.exit(app.exec_())

Looks like you want to draw items on QGraphicsScene? In this case you could add items to the scene:
#!/usr/bin/env python
import sys
from PyQt4 import QtCore, QtGui
class MainWidget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.scene = QtGui.QGraphicsScene()
self.view = QtGui.QGraphicsView(self.scene)
layout = QtGui.QVBoxLayout()
layout.addWidget(self.view)
self.setLayout(layout)
self.pixmap_item = QtGui.QGraphicsPixmapItem(QtGui.QPixmap('image.png'), None, self.scene)
self.pixmap_item.mousePressEvent = self.pixelSelect
self.click_positions = []
def pixelSelect(self, event):
self.click_positions.append(event.pos())
if len(self.click_positions) < 4:
return
pen = QtGui.QPen(QtCore.Qt.red)
self.scene.addPolygon(QtGui.QPolygonF(self.click_positions), pen)
for point in self.click_positions:
self.scene.addEllipse(point.x(), point.y(), 2, 2, pen)
self.click_positions = []
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
widget = MainWidget()
widget.resize(640, 480)
widget.show()
sys.exit(app.exec_())
QGraphicsScene has many features.
Read Graphics View Framework overview in Qt docs.

Related

pyqt5 Is there a limit to loading widgets using clicked.connect?

I'm using the QPushButton to load the UI. First -> Jumin -> Department -> next -> next I want to create the UI in order. The problem is that I can not load the third Department into the QMainwindow window. I do not know why
When you create a widget in QVBoxLayout, it changes the size of the widget according to the wallpaper like wxpython layout (wx.all). Can not change the position (move) and size (resize) by automatic centering?
import sys
from PyQt5.QtWidgets import *
class MainWindow(QMainWindow):
def __init__(self):
super().__init__()
self.center_widget = QWidget()
self.setCentralWidget(self.center_widget)
self.FirstUI()
def FirstUI(self):
self.btn1 = QPushButton('test1', self)
self.btn1.move(50, 50)
self.btn1.clicked.connect(self.btn1_click)
def JuminUI(self):
self.ju1 = QLineEdit('13')
self.btn2 = QPushButton('^^^^^^^^^^')
self.ju_text = QLabel('asd')
self.jumim_layout = QVBoxLayout()
self.jumim_layout.addWidget(self.ju_text)
self.jumim_layout.addWidget(self.ju1)
self.jumim_layout.addWidget(self.btn2)
self.centralWidget().setLayout(self.jumim_layout)
self.btn2.clicked.connect(self.btn2_click)
def DepartmentUI(self):
self.depart_layout = QVBoxLayout()
self.depart_layout.addWidget(QPushButton('sdfsdf'))
self.centralWidget().setLayout(self.depart_layout)
def btn1_click(self):
self.btn1.deleteLater()
self.JuminUI()
def btn2_click(self):
self.ju1.deleteLater()
self.btn2.deleteLater()
self.ju_text.deleteLater()
self.DepartmentUI()
if __name__ == "__main__":
app = QApplication(sys.argv)
fream = MainWindow()
fream.show()
app.exec_()
creating and removing widgets is almost always a bad idea, and your code falls into those bad ideas, it's always best to hide the widgets and for that you should use the QStackedWidget, what QStackedWidget does is just make a widget visible on all widgets that you have been assigned by changing the currentIndex.
import sys
from functools import partial
from PyQt5 import QtWidgets
class MainWindow(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.center_widget = QtWidgets.QStackedWidget()
self.setCentralWidget(self.center_widget)
self.FirstUI()
self.JuminUI()
self.DepartmentUI()
def FirstUI(self):
widget = QtWidgets.QWidget()
self.btn1 = QtWidgets.QPushButton('test1', widget)
self.btn1.move(50, 50)
self.center_widget.addWidget(widget)
self.btn1.clicked.connect(partial(self.center_widget.setCurrentIndex, 1))
def JuminUI(self):
widget = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(widget)
self.ju1 = QtWidgets.QLineEdit('13')
self.btn2 = QtWidgets.QPushButton('^^^^^^^^^^')
self.ju_text = QtWidgets.QLabel('asd')
lay.addWidget(self.ju_text)
lay.addWidget(self.ju1)
lay.addWidget(self.btn2)
self.center_widget.addWidget(widget)
self.btn2.clicked.connect(partial(self.center_widget.setCurrentIndex, 2))
def DepartmentUI(self):
widget = QtWidgets.QWidget()
lay = QtWidgets.QVBoxLayout(widget)
lay.addWidget(QtWidgets.QPushButton('sdfsdf'))
self.center_widget.addWidget(widget)
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
fream = MainWindow()
fream.show()
sys.exit(app.exec_())

How to move picbutton? Pyqt5 python

I want to make a button from a picture.
I found this code in here, but i cant move the picture, how can i do that?
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
class PicButton(QAbstractButton):
def __init__(self, pixmap, parent=None):
super(PicButton, self).__init__(parent)
self.pixmap = pixmap
def paintEvent(self, event):
painter = QPainter(self)
# painter.drawPixmap(100,1, self.pixmap)
painter.drawPixmap(500,1,100,100, self.pixmap,0,0,100,100)
def sizeHint(self):
return self.pixmap.size()
def close():
print("xxx")
app = QApplication(sys.argv)
window = QWidget()
layout = QHBoxLayout(window)
window.setFixedSize(740, 850) #window size.
button = PicButton(QPixmap("thinking.png"))
button.clicked.connect(close)
layout.addWidget(button)
window.show()
sys.exit(app.exec_())
I can move in x axis but cant in y axis.
How can i do that?
And is there any cursor style to make this more like button?
Thank you.
here is output

Click a button to change a GIF

In the App there are a QButton and a QLabel. In the QLabel I put a QMovie in, to show a GIF. By clicking the QButton I want to change the GIF, which path is defined in a list.
The problem: the App shows only the first GIF. The Button seems not working. What have I done wrong?
But: Please dont change the structure of the code. E.g. I want to have the QLabel defined in the sub-function and return from there the QLabel.
The code:
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import random
list = ['F:\\test1.gif', 'F:\\test2.gif', 'F:\\test3.gif', 'F:\\test4.gif']
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.resize(600, 600)
self.initUI()
def initUI(self):
self.btn = QPushButton("change", self)
self.btn.clicked.connect(self.changeGIF)
self.grid = QVBoxLayout()
self.grid.addWidget(self.btn)
self.grid.addWidget(self.changeGIF())
self.grid.addStretch(1)
self.setLayout(self.grid)
def changeGIF(self):
randomValue = list[random.randint(1, len(list)-1)]
print(randomValue)
self.lbl = QLabel()
self.gif = QMovie(randomValue)
self.lbl.setMovie(self.gif)
self.gif.start()
return self.lbl
if __name__ == '__main__':
app = QApplication(sys.argv)
MyApp = Window()
MyApp.show()
sys.exit(app.exec_())
Thanks for the help!
since the QLabel will be responsible for showing GIFs in a random way, it is advisable to create a class that only takes care of that task, in this widget you must have a method that changes the QMovie of the QLabel.
list_of_gifs = ['F:\\test1.gif', 'F:\\test2.gif', 'F:\\test3.gif', 'F:\\test4.gif']
class GIFLabel(QLabel):
def __init__(self, gifs, *args, **kwargs):
QLabel.__init__(self, *args, **kwargs)
self.mGifs = gifs
self.changeGIF()
def changeGIF(self):
gif = random.choice(self.mGifs)
movie = QMovie(gif)
self.setMovie(movie)
movie.start()
class Window(QWidget):
def __init__(self, parent=None):
super(Window, self).__init__(parent)
self.resize(600, 600)
self.initUI()
def initUI(self):
self.btn = QPushButton("change", self)
self.label = GIFLabel(list_of_gifs, self)
self.btn.clicked.connect(self.label.changeGIF)
self.grid = QVBoxLayout(self)
self.grid.addWidget(self.btn)
self.grid.addWidget(self.label)
self.grid.addStretch(1)
if __name__ == '__main__':
app = QApplication(sys.argv)
MyApp = Window()
MyApp.show()
sys.exit(app.exec_())

How to make a qframe highlight when cursor is on it in PyQt4?

I have the following window with frames.
I want frame to be highlighted (in my case change its shape) when mouse is in its area.
from PyQt4 import QtGui, QtCore
import sys
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window_layout = QtGui.QVBoxLayout()
window.setLayout(window_layout)
#fill content
for i in range(10):
label = QtGui.QLabel(str(i))
frame = QtGui.QFrame()
frame_layout = QtGui.QVBoxLayout()
frame.setLayout(frame_layout)
frame_layout.addWidget(label)
window_layout.addWidget(frame)
def layout_widgets(layout):
return (layout.itemAt(i) for i in range(layout.count()))
def mouse_enter(event):
print 'frame enter'
w.widget().setFrameShape(3)
def mouse_leave(event):
print 'frame leave'
w.widget().setFrameShape(0)
for w in layout_widgets(window_layout):
print w.widget()
w.widget().enterEvent = mouse_enter
w.widget().leaveEvent = mouse_leave
window.show()
sys.exit(app.exec_())
It works but only the last frame in layout highlights.
How to make only that frame change its shape where the mouse is?
I've tried the following:
def mouse_enter(event, frame):
print 'frame enter'
frame.setFrameShape(3)
w.widget().enterEvent = functools.partial(mouse_enter, w.widget())
but it gives an error. I have found one more way to do that - signal mapper
but I have no idea how to use it.
The problem in your code the variable w when executing the for is left with the last element, so it will only be executed in the latter. To solve this I have implemented a Frame class that inherits from QFrame where I overwrite the enterEvent and leaveEvent functions.
from PyQt4 import QtGui, QtCore
import sys
class Frame(QtGui.QFrame):
def __init__(self, text, parent=None):
super(Frame, self).__init__(parent=parent)
label = QtGui.QLabel(text)
frame_layout = QtGui.QVBoxLayout()
frame_layout.addWidget(label)
self.setLayout(frame_layout)
def enterEvent(self, event):
self.setFrameShape(3)
def leaveEvent(self, event):
self.setFrameShape(0)
app = QtGui.QApplication(sys.argv)
window = QtGui.QWidget()
window_layout = QtGui.QVBoxLayout()
window.setLayout(window_layout)
for i in range(10):
frame = Frame(str(i))
window_layout.addWidget(frame)
window.show()
sys.exit(app.exec_())

How to fit widgets within frame in python

I am pretty new at python but currently I am getting some problem here with the part where I am unable to get my stuff fit within the width of the window.
I am trying to set it in such a way that it is:
Eg. Name Button
by the way, I am using Maya to integrate and run my stuff.
If I set it to central, it fits but it is all over the place as I only wanted it to occupy a portion only. So are there any ways for me to fit it nicely into it?
By the way, if its possible, can it be done using my current codings?
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sip
import maya.OpenMayaUI as mui
import os
class MainWindow(QMainWindow):
def __init__(self, parent = None):
QMainWindow.__init__(self,parent)
self.resize(400,800)
self.setWindowTitle("GetShots")
self.pubDock = SetShotInfo()
self.pubDW = QDockWidget(self.tr(""), self)
self.pubDW.setWidget(self.pubDock)
# self.setCentralWidget(self.pubDW)
def getMayaWindow():
ptr = mui.MQtUtil.mainWindow()
return sip.wrapinstance(long(ptr), QObject)
def main():
global app
global form
app = qApp
form = MainWindow(getMayaWindow())
form.show()
class GetShot(QFrame):
def __init__(self, parent = None, display=None):
QFrame.__init__(self, parent)
self.createWidgets()
self.createLayout()
def createWidgets(self):
self.showLabel = QLabel('Show')
self.showName = QLineEdit()
self.showName.setText(str(os.environ['SHOW']))
self.shotLabel = QLabel('Shot Filter')
self.shotName = QLineEdit()
self.showButton = QPushButton('Set Show')
self.showButton.setMaximumWidth(200)
self.shotButton = QPushButton('Filter Shots')
self.shotButton.setMaximumWidth(200)
self.rootLabel = QLabel('Change Root')
self.rootButton = QComboBox()
def createLayout(self):
# Sets the Layout of Show and Shot
setShowLayout = QHBoxLayout()
setShowLayout.addWidget(self.showLabel)
setShowLayout.addWidget(self.showName)
setShowLayout.addWidget(self.showButton)
setShotLayout = QHBoxLayout()
setShotLayout.addWidget(self.shotLabel)
setShotLayout.addWidget(self.shotName)
setShotLayout.addWidget(self.shotButton)
# Sets the Change Root Layout
chgRootLayout = QHBoxLayout()
chgRootLayout.addWidget(self.rootLabel)
chgRootLayout.addWidget(self.rootButton)
mainLayout = QVBoxLayout()
mainLayout.addLayout(setShowLayout)
mainLayout.addLayout(setShotLayout)
mainLayout.addLayout(chgRootLayout)
self.setLayout(mainLayout)
if __name__ == '__main__':
main()
You need to use Layouts, combine vertical and horizontal and play with the size policy of the widgets to fit them as you need.
Here's a quick example:
import sys
from PyQt4 import QtCore, QtGui
class ButtonContainer(QtGui.QWidget):
def __init__(self):
super(ButtonContainer, self).__init__()
self.initUI()
def initUI(self):
self.setGeometry( 150, 150, 650, 350)
btn = QtGui.QPushButton('Name button', self)
btn.setSizePolicy( QtGui.QSizePolicy( QtGui.QSizePolicy.Minimum, QtGui.QSizePolicy.Fixed ) )
vbox = QtGui.QVBoxLayout()
vbox.addWidget( btn )
self.setLayout(vbox)
self.show()
app = QtGui.QApplication(sys.argv)
ex = ButtonContainer()
sys.exit(app.exec_())
The commenters are right in suggesting QtDesigner, if you'd rather code it yourself at least have a mock up ui file where you can play interactively with the layouts and size policies, it's really helpful.

Categories

Resources