How can I change size of circle in first window, using slider from second window. Is there an option to send value from slider to first window and put this value in painter.drawEllipse fuction?
class ThirdWindow(QWidget):
def __init__(self):
super().__init__()
hbox = QHBoxLayout()
sld = QSlider(Qt.Horizontal, self)
sld.setRange(0, 100)
sld.setFocusPolicy(Qt.NoFocus)
sld.setPageStep(5)
sld.valueChanged.connect(self.updateLabel)
self.label = QLabel('0', self)
self.label.setAlignment(Qt.AlignCenter | Qt.AlignVCenter)
self.label.setMinimumWidth(80)
hbox.addWidget(sld)
hbox.addSpacing(15)
hbox.addWidget(self.label)
self.setLayout(hbox)
self.setGeometry(600, 60, 500, 500)
self.setWindowTitle('QSlider')
self.show()
def updateLabel(self, value):
self.label.setText(str(value))
class Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle("Dialogi")
self.w = ThirdWindow()
actionFile = self.menuBar().addMenu("Dialog")
action = actionFile.addAction("Zmień tło")
action1 = actionFile.addAction("Zmień grubość koła")
action1.triggered.connect(self.w.show)
self.setGeometry(100, 60, 300, 300)
self.setStyleSheet("background-color: Green")
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.gray, 8, Qt.SolidLine))
painter.drawEllipse(100, 100, 100, 100)
You can communicate with the parent class (in this case the class where the circle is located i.e. Window by calling self.parentWidget()
so you can call that inside your updateLabel function and pass the value. However to repaint the surface you must have a variable initiated in the main Window
Hence your code should look like-
class Window(QMainWindow):
def __init__(self):
QMainWindow.__init__(self)
self.setWindowTitle("Dialogi")
self.w = ThirdWindow()
actionFile = self.menuBar().addMenu("Dialog")
action = actionFile.addAction("Zmień tło")
action1 = actionFile.addAction("Zmień grubość koła")
action1.triggered.connect(self.w.show)
self.setGeometry(100, 60, 300, 300)
self.setStyleSheet("background-color: Green")
self.radius = 100 #add a variable radius to keep track of the circle radius
def paintEvent(self, event):
painter = QPainter(self)
painter.setPen(QPen(Qt.gray, 8, Qt.SolidLine))
#change function to include radius
painter.drawEllipse(100, 100, self.radius, self.radius)
and in the other widget change the updateLabel function to change the radius and call repaint
class ThirdWindow(QWidget):
def updateLabel(self, value):
self.label.setText(str(value))
self.parentWidget().radius = value
self.parentWidget().repaint()
Related
import sys
from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import QApplication,QDialog,QPushButton,QVBoxLayout,QWidget
class Main(QDialog):
def __init__(self):
super(Main, self).__init__()
self.ui()
# Group Of Drage Event
def mousePressEvent(self,event):
self.offset = event.pos()
def mouseMoveEvent(self, e):
x = e.globalX()
y = e.globalY()
x_w = self.offset.x()
y_w = self.offset.y()
self.move(x - x_w, y - y_w)
def ui(self):
# TitleBar
self.setWindowFlags(Qt.FramelessWindowHint)
# Window Size
self.setGeometry(600,300,400,500)
# Window Background Color
self.BackGroundColor = QPalette()
self.BackGroundColor.setColor(QPalette.Background, QColor(255,255,255))
self.setPalette(self.BackGroundColor)
# NavBar Button
self.btn = QPushButton('Test',self)
self.btn1 = QPushButton("Test1",self)
# NavBar Layout
self.layout = QVBoxLayout(self)
self.layout.addWidget(self.btn)
self.layout.addWidget(self.btn1)
self.layout.set
self.setLayout(self.layout)
# Close img
self.closeBtn = QPushButton(self)
self.closeBtn.setGeometry(368,0,32,32)
self.closeBtn.setFlat(True)
self.closeBtn.setStyleSheet('QPushButton{background-color: rgba(0,0,0,0.0)}')
self.closeBtn.setIcon(QIcon('img/close.png'))
self.closeBtn.setIconSize(QSize(10,10))
self.closeBtn.clicked.connect(QCoreApplication.instance().quit)
# Maximize icon
self.maxBtn = QPushButton(self)
self.maxBtn.setGeometry(self,336,0,32,32)
self.maxBtn.setFlat(True)
self.maxBtn.setStyleSheet('QPushButton{background-color: rgba(0,0,0,0.0)}')
self.maxBtn.setIcon(QIcon('img/max.png'))
self.maxBtn.setIconSize(QSize(14,14))
# Minimize Incon
self.minBtn = QPushButton(self)
self.minBtn.setGeometry(304,0,32,32)
self.minBtn.setFlat(True)
self.minBtn.setStyleSheet('QPushButton{background-color: rgba(0,0,0,0.0)}')
self.minBtn.setIcon(QIcon('img/min.png'))
self.minBtn.setIconSize(QSize(10,10))
def main():
app = QApplication()
win = Main()
win.show()
app.exec_()
if __name__ == "__main__":
main()
I want to fixed navbar on the left. So, I create instance of QVBoxLayout and add widget to my Layout. and I had searched google, stackoverflow. i Don't get any information about my problem
but I don't know how to set layout widget. please teach me. Thank you.
if you don't understand my text please tell me i will describe that
Version:
PySide 5.14.2.1
Python 3.7.7
The layouts are not visual elements, so they do not have any geometric element associated with them, such as the width size, the layout is a handle of size and positions.
In this case the solution is to establish a container with a fixed size and in that container place the buttons with the help of a layout:
class Main(QDialog):
def __init__(self):
super(Main, self).__init__()
self.ui()
# Group Of Drage Event
def mousePressEvent(self, event):
self.offset = event.pos()
def mouseMoveEvent(self, e):
x = e.globalX()
y = e.globalY()
x_w = self.offset.x()
y_w = self.offset.y()
self.move(x - x_w, y - y_w)
def ui(self):
# TitleBar
self.setWindowFlags(Qt.FramelessWindowHint)
# Window Size
self.setGeometry(600, 300, 400, 500)
# Window Background Color
self.BackGroundColor = QPalette()
self.BackGroundColor.setColor(QPalette.Background, QColor(255, 255, 255))
self.setPalette(self.BackGroundColor)
# NavBar Button
self.btn = QPushButton("Test")
self.btn1 = QPushButton("Test1")
left_container = QWidget(self)
left_container.setFixedWidth(100)
# NavBar layout
self.layout = QVBoxLayout(left_container)
self.layout.addWidget(self.btn)
self.layout.addWidget(self.btn1)
hlay = QHBoxLayout(self)
hlay.addWidget(left_container)
hlay.addStretch()
# Close img
self.closeBtn = QPushButton(self)
self.closeBtn.setGeometry(368, 0, 32, 32)
self.closeBtn.setFlat(True)
self.closeBtn.setStyleSheet("QPushButton{background-color: rgba(0,0,0,0.0)}")
self.closeBtn.setIcon(QIcon("img/close.png"))
self.closeBtn.setIconSize(QSize(10, 10))
self.closeBtn.clicked.connect(QCoreApplication.instance().quit)
# Maximize icon
self.maxBtn = QPushButton(self)
self.maxBtn.setGeometry(336, 0, 32, 32)
self.maxBtn.setFlat(True)
self.maxBtn.setStyleSheet("QPushButton{background-color: rgba(0,0,0,0.0)}")
self.maxBtn.setIcon(QIcon("img/max.png"))
self.maxBtn.setIconSize(QSize(14, 14))
# Minimize Incon
self.minBtn = QPushButton(self)
self.minBtn.setGeometry(304, 0, 32, 32)
self.minBtn.setFlat(True)
self.minBtn.setStyleSheet("QPushButton{background-color: rgba(0,0,0,0.0)}")
self.minBtn.setIcon(QIcon("img/min.png"))
self.minBtn.setIconSize(QSize(10, 10))
I have been trying to learn to using PyQt5.
I want to implement a canvas below the "Menu Bar"
class gui(QDialog):
def __init__(self, parent=None):
super(gui, self).__init__(parent)
self.createTopLayout()
self.painter = canvas(self)
mainLayout = QGridLayout()
mainLayout.addLayout(self.topLayout, 0, 0, 1, 2)
mainLayout.addWidget(self.painter, 1, 0, 6, 2)
self.setLayout(mainLayout)
def createTopLayout(self):
self.topLayout = QHBoxLayout()
button1 = QPushButton("b1")
button2 = QPushButton("b2")
button3 = QPushButton("b3")
styleComboBox = QComboBox()
styleComboBox.addItems(QStyleFactory.keys())
styleLabel = QLabel("&Style:")
styleLabel.setBuddy(styleComboBox)
self.topLayout.addWidget(styleLabel)
self.topLayout.addWidget(styleComboBox)
self.topLayout.addStretch(1)
self.topLayout.addWidget(button1)
self.topLayout.addWidget(button2)
self.topLayout.addWidget(button3)
Where my canvas is defined as
class canvas(QMainWindow):
def __init__(self, parent=None):
super(canvas, self).__init__(parent)
self.setGeometry(100, 100, 1000, 700)
def paintEvent(self, e):
cir = circle() #circle class creates a circle with random center and radius both between 0 to 100
painter = QPainter(self)
painter.setPen(QPen(Qt.red, 1, Qt.SolidLine))
painter.drawEllipse(self, cir.center.x, cir.center.y, cir.radius, cir.radius)
but for me canvas doesnt render at all let alone the ellipse.
You should not use QMainWindow as a canvas, instead use a QWidget. On the other hand setGeometry will not work if you use layout since the latter handles the geometry, instead it establishes a fixed size and adequate margins. On the other hand it is recommended that the name of the classes begin with capital letters, considering the above the solution is:
class Canvas(QWidget):
def __init__(self, parent=None):
super(Canvas, self).__init__(parent)
self.setFixedSize(1000, 700)
self.setContentsMargins(100, 100, 100, 100)
def paintEvent(self, e):
# ...
I want to move the ligne of labels to the left by adding to their coordinate 100 every time I push a specific button.
I tied to call the show tab function inside the move_ligne_one() function but I cant refer to it
class App(QWidget):
def __init__(self):
super().__init__()
self.title = 'Simple window'
self.left = 100
self.top = 100
self.width = 1100
self.height = 800
self.initUI()
def initUI(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
self.setWindowIcon(QIcon("img/icon.png"))
def show_tab(left_cord):
ligne_1_left_cord = left_cord
label_ligne_1_1 = QtWidgets.QLabel(self)
#pic_signe_x =QPixmap('img/x.png')
#label_ligne_1_1.setPixmap(pic_signe_x)
label_ligne_1_1.setText("X")
label_ligne_1_1.move(ligne_1_left_cord,300)
label_ligne_1_2 = QtWidgets.QLabel(self)
#pic_signe_x =QPixmap('img/x.png')
#label_ligne_1_1.setPixmap(pic_signe_x)
label_ligne_1_2.setText("X")
label_ligne_1_2.move( ligne_1_left_cord +200,300)
label_ligne_1_3 = QtWidgets.QLabel(self)
#pic_signe_x =QPixmap('img/x.png')
#label_ligne_1_1.setPixmap(pic_signe_x)
label_ligne_1_3.setText("X")
label_ligne_1_3.move( ligne_1_left_cord +400,300)
label_ligne_1_4 = QtWidgets.QLabel(self)
#pic_signe_x =QPixmap('img/x.png')
#label_ligne_1_1.setPixmap(pic_signe_x)
label_ligne_1_4.setText("X")
label_ligne_1_4.move( ligne_1_left_cord +600,300)
buttonStart = QPushButton('START', self)
buttonStart.setGeometry(380, 700, 250, 61)
buttonStart.clicked.connect(self.on_click)
button_left_1 = QPushButton('<', self)
button_left_1.setGeometry(45,300,30,30)
button_left_1.clicked.connect(self.move_ligne_one)
show_tab(275)
self.show()
#pyqtSlot()
def move_ligne_one(self):
print(' button click')
If you want to move a widget then the first thing is to access that widget so you have to do it class attribute:
# ...
self.label_ligne_1_1 = QtWidgets.QLabel(self)
# ...
self.label_ligne_1_2 = QtWidgets.QLabel(self)
# ...
self.label_ligne_1_3 = QtWidgets.QLabel(self)
# ...
self.label_ligne_1_4 = QtWidgets.QLabel(self)
# ...
And then modify the position:
#pyqtSlot()
def move_ligne_one(self):
for btn in (
self.label_ligne_1_1,
self.label_ligne_1_2,
self.label_ligne_1_3,
self.label_ligne_1_4,
):
p = btn.pos()
p += QtCore.QPoint(100, 0)
btn.move(p)
I'm trying to get an image to fit my label entirely without using setScaledContents(True) since I'd like my ImageGrab to have the exact same dimensions as the QLabel space.
I use a PIL ImageGrab with a bbox. if I chance the parameters to a wider width and higher height it will crash the program without any errors. I have attached a picture where the Image in the Label is localed left center. I'd like it to the top left. So that it can expand down and to the right if I increased the size.
But I am curious as to why I am unable to increase the size of the bbox. (0, 0, 400, 220) works fine but (0, 0, 420, 220) will not upload the Image and closes down the GUI without any errors.
I'd like to have a ImageGrab with bbox (0, 0, 800, 700) and a QLabel with size(800, 700) so it can fit it perfectly.
class Main(QMainWindow):
def __init__(self, parent=None):
QWidget.__init__(self, parent)
self.setGeometry(200, 200, 1000, 700)
self.setWindowTitle('threads')
self.mainFrame = QFrame(self)
self.mainFrame.resize(1000, 650)
self.mainFrame.move(0, 50)
self.mainFrame.setStyleSheet("background-color: rbg(50, 50, 50)")
self.testButton = QPushButton("Click", self)
self.testButton.resize(500,30)
self.connect(self.testButton, SIGNAL("clicked()"), self.Capture)
self.label_ = QLabel(self.mainFrame)
self.label_.move(10, 10)
self.label_.resize(980, 630)
self.label_.setStyleSheet("background-color: rbg(150, 150, 150)")
#pyqtSlot(QImage)
def ChangeFrame(self, image):
pixmap = QPixmap.fromImage(image)
self.label_.setPixmap(pixmap)
def Capture(self):
self.thread_ = CaptureScreen()
self.connect(self.thread_, SIGNAL("ChangeFrame(QImage)"), self.ChangeFrame, Qt.QueuedConnection)
self.thread_.start()
class CaptureScreen(QThread):
pixmap = pyqtSignal(QImage)
def __init__(self, parent = None):
QThread.__init__(self)
def __del__(self):
print("?????")
self.exiting = True
self.wait()
def run(self):
while(True):
time.sleep(1/60)
img = ImageGrab.grab(bbox=(0, 0, 420, 220))
frame = ImageQt(img)
frame = QImage(frame)
self.emit( SIGNAL("ChangeFrame(QImage)"), frame)
The solution is to use layouts, and set the alignment in QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft.
I also recommend using the new connection syntax, on the other hand if you are going to inherit from QMainWindow in the constructor you must call it. And finally when you use QMainWindow you must set a central widget.
import time
from PyQt4 import QtCore, QtGui
from PIL import ImageGrab, ImageQt
class Main(QtGui.QMainWindow):
def __init__(self, parent=None):
QtGui.QMainWindow.__init__(self, parent)
self.setGeometry(200, 200, 1000, 700)
self.setWindowTitle('threads')
main_widget = QtGui.QWidget()
self.setCentralWidget(main_widget)
lay = QtGui.QVBoxLayout(main_widget)
self.testButton = QtGui.QPushButton("Click")
self.testButton.setFixedHeight(30)
self.testButton.clicked.connect(self.capture)
mainFrame = QtGui.QFrame()
mainFrame.setStyleSheet("background-color: rbg(50, 50, 50)")
_lay = QtGui.QVBoxLayout(mainFrame)
_lay.setContentsMargins(0, 0, 0, 0)
self.label_ = QtGui.QLabel()
_lay.addWidget(self.label_, 0, QtCore.Qt.AlignTop|QtCore.Qt.AlignLeft)
lay.addWidget(self.testButton)
lay.addWidget(mainFrame)
#QtCore.pyqtSlot(QtGui.QImage)
def changeFrame(self, image):
pixmap = QtGui.QPixmap.fromImage(image)
self.label_.setPixmap(pixmap)
#QtCore.pyqtSlot()
def capture(self):
self.thread_ = CaptureScreen()
self.thread_.changedFrame.connect(self.changeFrame, QtCore.Qt.QueuedConnection)
self.thread_.start()
self.testButton.setDisabled(True)
class CaptureScreen(QtCore.QThread):
changedFrame = QtCore.pyqtSignal(QtGui.QImage)
def __del__(self):
print("?????")
self.exiting = True
self.quit()
self.wait()
def run(self):
while True:
time.sleep(1/60)
w, h = 420, 220
img = ImageGrab.grab(bbox=(0, 0, w, h))
frame = ImageQt.toqimage(img)
self.changedFrame.emit(QtGui.QImage(frame))
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = Main()
w.show()
sys.exit(app.exec_())
I present here a simple pyqt code, but I developed my whole design and algo upon this. The problem, is that PyQt is unable to manage a large number of objects when created. This is simple code for drawing many rectangles inside a big one. And it has Zoom and pan feature too.
import sys
from PyQt4 import QtGui, QtCore
from PyQt4.QtCore import *
from PyQt4.QtGui import *
item = None
class Rectangle(QGraphicsItem):
def __init__(self, parent, x, y, width, height, scene = None, fill=None):
self.parent = parent
super(Rectangle, self).__init__()
self.setFlags(QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
rect = QRectF(x,y,width,height)
self.dimen = [x,y,width,height]
self.rect = rect
scene.addItem(self)
self.show_its_ui()
#Function to get relative position
def get_relative_location(self,loc):
self.loc = QPointF(loc[0],loc[1])
global item
self.loc = self.mapFromItem(item, self.loc)
self.loc = (self.loc.x(),self.loc.y())
self.loc = list(self.loc)
self.dimen[0] = self.loc[0]
self.dimen[1] = self.loc[1]
#Showing its UI in the form of a rectangle
def show_its_ui(self):
#First gets its relative location and set it.
if(item is not None):
self.get_relative_location([self.dimen[0],self.dimen[1]])
#Make a Final rectangle
rect = QRectF(self.dimen[0],self.dimen[1],self.dimen[2],self.dimen[3])
self.rect = rect
def boundingRect(self):
return self.rect.adjusted(-2, -2, 2, 2)
def parentWidget(self):
return self.scene().views()[0]
def paint(self, painter, option, widget):
pen = QPen(Qt.SolidLine)
pen.setColor(Qt.black)
pen.setWidth(1)
painter.setBrush(QtGui.QColor(255, 50, 90, 200))
painter.drawRect(self.rect)
class GraphicsView(QGraphicsView):
def __init__(self, parent=None):
super(GraphicsView, self).__init__(parent)
self.setDragMode(QGraphicsView.RubberBandDrag)
self.setRenderHint(QPainter.Antialiasing)
self.setRenderHint(QPainter.TextAntialiasing)
def wheelEvent(self, event):
factor = 1.41 ** (event.delta() / 240.0)
self.scale(factor, factor)
class MainWindow(QtGui.QMainWindow):
def __init__(self, parent = None):
QtGui.QMainWindow.__init__(self, parent)
self.Width = 800
self.Height = 500
self.view = GraphicsView()
self.scene = QGraphicsScene(self)
self.scene.setSceneRect(0, 0, self.Width, self.Height)
self.view.setScene(self.scene)
self.initUI()
hbox = QtGui.QHBoxLayout()
hbox.addWidget(self.view)
mainWidget = QtGui.QWidget()
mainWidget.setLayout(hbox)
self.setCentralWidget(mainWidget)
def initUI(self):
self.group = QGraphicsItemGroup()
self.group.setFlags(QGraphicsItem.ItemIsFocusable | QGraphicsItem.ItemIsMovable | QGraphicsItem.ItemIsSelectable)
global item
item = self.group
self.group.setFiltersChildEvents(True)
self.group.setHandlesChildEvents(False)
self._link1 = Rectangle(self, 10, 10, self.Width, self.Height,self.scene)
self._link1.setFiltersChildEvents(True)
self._link1.setHandlesChildEvents(False)
self.group.addToGroup(self._link1)
self.scene.addItem(self.group)
self.addObjects()
#Here I added objects in the big canvas
def addObjects(self):
xpos = 20
ypos = 20
#Change the below to 5 each
width = 50
height = 50
#Generate many rectangles
while(ypos < 450):
xpos = 20
while(xpos < 750):
t = Rectangle(self._link1,xpos,ypos,width,height,self.scene,True)
self.group.addToGroup(t)
xpos += (width+2)
ypos += (height+2)
app = QtGui.QApplication(sys.argv)
mainWindow = MainWindow()
method = mainWindow
mainWindow.show()
sys.exit(app.exec_())
Try changing, the width and height values present in addObjects function of the mainwindow class, say to 5 and 5 respectively from 50. Then the whole application run at very slow speed, when you pan/zoom. Please share your suggestions in rectifying this.