from PyQt5.QtWidgets import QApplication, QLabel, QWidget, QFileDialog, QPushButton, QLineEdit,QVBoxLayout, QHBoxLayout
from PyQt5.QtCore import *
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QDialog, QVBoxLayout
import Updated_encrypt
import sys
class Window(QWidget):
def __init__(self):
super().__init__()
self.title = 'Encrypt/Decrypt'
self.top = 200
self.left = 500
self.width = 400
self.height = 300
self.InitWindow()
def InitWindow(self):
self.setWindowTitle(self.title)
self.setGeometry(self.left, self.top, self.width, self.height)
vbox = QVBoxLayout()
self.button1 = QPushButton('Encrypt')
self.button1.clicked.connect(self.openSecondDialog)
self.button2 = QPushButton('Decrypt')
vbox.addWidget(self.button1)
vbox.addWidget(self.button2)
self.setLayout(vbox)
self.show()
def openSecondDialog(self):
hbox = QVBoxLayout()
mydialog = QDialog(self)
mydialog.show()
self.button2 = QPushButton('Check Image')
self.button2.clicked.connect(self.getImage)
hbox.addWidget(self.button2)
self.setLayout(hbox)
self.show()
def getImage(self):
hbox = QHBoxLayout()
file_Name = QFileDialog.getOpenFileName(self,
'OpenFile',
'',
'')
image_path = file_Name[0]
updatedImage = Updated_encrypt.decrypt(image_path, 123)
pixmap = QPixmap(updatedImage)
self.label.setPixmap(QPixmap(pixmap))
self.resize(pixmap.width(), pixmap.height())
App = QApplication(sys.argv)
window = Window()
sys.exit(App.exec())
I have my code set up to implement an algorithm to modify an image when my I select it from my pop up dialogue. What I am trying to accomplish is for the image to pop up in a separate window when I click the encrypt button. I can't seem to get anything to pop up in the separate window aside from the window itself. Any help would be appreciated.
You have at least the following errors:
The "hbox" created is being added to the window and not to the QDialog: self.setLayout(hbox), it must be mydialog.setLayout(hbox).
Do not use the same name for 2 different objects as they can cause problems, in your case there are 2 QPushButton assigned to the variable "self.button2".
You try to use the variable "self.label" but never believe it.
Considering the above we can make the following improvements:
Use more descriptive names to easily distinguish their function.
If you are going to have a window that has a different objective, it is better to create a class.
The above avoid the indicated problems, considering the above the solution is:
import sys
from PyQt5.QtGui import QPixmap
from PyQt5.QtWidgets import (
QApplication,
QDialog,
QFileDialog,
QHBoxLayout,
QLabel,
QPushButton,
QVBoxLayout,
QWidget,
)
import Updated_encrypt
class Dialog(QDialog):
def __init__(self, parent=None):
super().__init__(parent)
self.load_image_btn = QPushButton("Check Image")
self.load_image_btn.clicked.connect(self.load_image)
self.image_lbl = QLabel()
lay = QVBoxLayout(self)
lay.addWidget(self.load_image_btn)
lay.addWidget(self.image_lbl)
def load_image(self):
image_path, _ = QFileDialog.getOpenFileName(self, "OpenFile", "", "")
if image_path:
updatedImage = Updated_encrypt.decrypt(image_path, 123)
pixmap = QPixmap(updatedImage)
self.image_lbl.setPixmap(QPixmap(pixmap))
class Window(QWidget):
def __init__(self, parent=None):
super().__init__(parent)
self.title = "Encrypt/Decrypt"
self.InitWindow()
def InitWindow(self):
self.setWindowTitle(self.title)
self.setGeometry(200, 500, 400, 300)
self.encrypt_btn = QPushButton("Encrypt")
self.encrypt_btn.clicked.connect(self.openSecondDialog)
self.decrypt_btn = QPushButton("Decrypt")
vbox = QVBoxLayout(self)
vbox.addWidget(self.encrypt_btn)
vbox.addWidget(self.decrypt_btn)
def openSecondDialog(self):
dialog = Dialog(self)
dialog.show()
if __name__ == "__main__":
app = QApplication(sys.argv)
window = Window()
window.show()
sys.exit(app.exec())
Trying to animate a line growing from nothing to a (0,0) to (200, 200) line with PyQt5 and using QPropertyAnimation. I already read a lot of documentation about Qt and tried several samples, but I just cannot get this to work. This is the code I have now:
from PyQt5 import QtCore
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QPainter, QPixmap, QPainterPath
from PyQt5.QtCore import QObject, QPointF, QPropertyAnimation, pyqtProperty
from PyQt5.QtCore import QLineF
import sys
class Sample(QWidget):
l1 = QLineF(QPointF(), QPointF())
def __init__(self):
super().__init__()
self.initView()
self.initAnimation()
def initView(self):
self.show()
def initAnimation(self):
self.anim = QPropertyAnimation(self.l1, b'geometry')
self.anim.setDuration(7000)
self.anim.setStartValue(QPointF(0, 0))
self.anim.setEndValue(QPointF(200, 200))
self.anim.start()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Sample()
sys.exit(app.exec_())
Not posting all previous attemps, each one fails with a different error. I got a fade out animation on a widget to work, and a picture following a path, but I can seem to make a simple line drawing work. I was hoping to achieve something like this:
Codepen example
Qt documentation is huge and it seems there are several ways to achieve this, painter and timer, animation, variant animation, but I am not very familiar with C++ and the translation to Python is not always easy. Also samples are not that easy to find.
Am I missing something obvious?
Thanks!
For the record, this is what I achieved so far but as soon as I un-comment the QPropertyAnimation creation, app does not launch. Anyway I was still far from the result in the accepted answer.
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import sys
class MyLine(QGraphicsLineItem, QObject):
def __init__(self):
super().__init__()
def _set_start(self, point):
self.setLine(point.x(), point.y(), self.line().p2().x(), self.line().p2().y())
def _set_end(self, point):
self.setLine(self.line().p1().x(), self.line().p1().y(), point.x(), point.y())
start = pyqtProperty(QPointF, fset=_set_start)
end = pyqtProperty(QPointF, fset=_set_end)
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
hbox = QHBoxLayout(self)
self.button = QPushButton("Start", self)
self.button.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed)
hbox.addWidget(self.button)
hbox.addSpacing(40)
self.line = MyLine()
self.line.setLine(0, 0, 10, 10)
scene = QGraphicsScene()
scene.addItem(self.line)
view = QGraphicsView(scene)
hbox.addWidget(view)
self.anim = QPropertyAnimation(self.line, b"end") # crash without error here
# self.anim.setDuration(2500)
# self.anim.setLoopCount(1)
# self.anim.setStartValue(QPointF(10, 10))
# self.anim.setEndValue(QPointF(200, 200))
# self.button.clicked.connect(self.anim.start)
self.setGeometry(300, 300, 380, 250)
self.setWindowTitle('Color anim')
self.show()
if __name__ == "__main__":
app = QApplication([])
ex = Example()
ex.show()
app.exec_()
You have to use QGraphicsView, QGraphicsScene with QGraphicsLineItem as I show below:
from PyQt5 import QtCore, QtGui, QtWidgets
class LineAnimation(QtCore.QObject):
def __init__(self, parent=None):
super(LineAnimation, self).__init__(parent)
self.m_line = QtCore.QLineF()
self.m_item = QtWidgets.QGraphicsLineItem()
self.m_item.setLine(self.m_line)
self.m_item.setPen(
QtGui.QPen(
QtGui.QColor("salmon"),
10,
QtCore.Qt.SolidLine,
QtCore.Qt.SquareCap,
QtCore.Qt.RoundJoin,
)
)
self.m_animation = QtCore.QPropertyAnimation(
self,
b"p2",
parent=self,
startValue=QtCore.QPointF(0, 0),
endValue=QtCore.QPointF(200, 200),
duration=5 * 1000,
)
self.m_animation.start()
def p1(self):
return self.m_line.p1()
def setP1(self, p1):
self.m_line.setP1(p1)
self.m_item.setLine(self.m_line)
def p2(self):
return self.m_line.p2()
def setP2(self, p2):
self.m_line.setP2(p2)
self.m_item.setLine(self.m_line)
p1 = QtCore.pyqtProperty(QtCore.QPointF, fget=p1, fset=setP1)
p2 = QtCore.pyqtProperty(QtCore.QPointF, fget=p2, fset=setP2)
class MainWindow(QtWidgets.QMainWindow):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
scene = QtWidgets.QGraphicsScene(self)
view = QtWidgets.QGraphicsView(
scene, alignment=QtCore.Qt.AlignLeft | QtCore.Qt.AlignTop
)
self.setCentralWidget(view)
line_animation = LineAnimation(self)
scene.addItem(line_animation.m_item)
if __name__ == "__main__":
import sys
app = QtWidgets.QApplication(sys.argv)
w = MainWindow()
w.resize(640, 480)
w.show()
sys.exit(app.exec_())
I've created aQMainWindow with menubar and 4 dockable widgets. First dockwidget contents multipletabs, second is Qpainter widget, third is Matlabplot and fourth is pdf report.
When I run the code shows up like this below.
I want to be like below.
I want to divide screen into four widget automatically whenever it runs at any screen, And I want to have tabs to resize to its content.
Or do you have any better idea of having such widget, you are welcome to come with it.
Update of code
Resize of Qdockwidget brings this post forward. It seems that Qt Qdockwidget resize has been an issue for long time ago. I find it very difficult to program my Qmainwindow with 4 Qdockwidget, which the dock would fit and resize according to its contents, with other words, child widget. and According to Qt documentation, Qdockwidget resizes and respect the size of child Widgets. to get straight to problem, my mainwindow has 4 qdockwidgets, I would like to have them resizable according to contents.
What I have tried and used so far.
I have used following size functions.
self.sizeHint, self.minimumSize(), self.maximumSize() and self.setFixedSize(self.sizeHint()).
I am able to fix the size of contents in first Qdockwidget by using following codes.
self.setFixedSize(self.sizeHint())
Above code is written in the child widgets Class widgets
But that is not enough in order to work it, despite following codes needed to run and effect.
self.first.setMinimumSize(self.first.sizeHint())
self.grid.setMinimumSize(self.grid.sizeHint())
self.third.setMinimumSize(self.third.sizeHint())
self.adjustSize()
self.first.setMinimumSize(self.first.minimumSizeHint())
self.grid.setMinimumSize(self.grid.minimumSizeHint())
self.third.setMinimumSize(self.third.minimumSizeHint())
Noting that still my dockwindow does not resize according to child widgets. Dockwidget expand and increase. One may ask, Qdockwidgets could arrange and control by resizeDocks(). This code line is used and tried, but still does not get the desired behaviour.
I have been looking around and could find some relevant questions.
C++ resize a docked Qt QDockWidget programmatically?
Forcing a QDockWidget to behave like a central widget when it comes to resizing
Create a QDockWidget that resizes to it's contents
Those questions do not solve my problem.
Visualization of my code launch
1- When code runs and display on screen.
2- Desired and wanted display by first run of software.
3- When user tabs between tabwidgets want to resize to its content as image below.
4- The code is given below.
import sys, os
from PyQt5 import QtCore, QtWidgets, QtGui
from PyQt5.QtWidgets import QMainWindow, QLabel, QGridLayout, QWidget,
QDesktopWidget, QApplication, QAction, QFileDialog,QColorDialog
from PyQt5.QtWidgets import QPushButton, QMessageBox, QDockWidget,
QTabWidget, QVBoxLayout, QGroupBox, QHBoxLayout, QFrame, QSplitter
from PyQt5.QtWidgets import QTableWidget, QRadioButton, QListWidget,
QCheckBox, QTextEdit, QDialog, QSizePolicy
from PyQt5.QtCore import QSize, Qt, QFileInfo, QFile
from PyQt5.QtGui import QIcon, QKeySequence, QPainter, QPalette, QPen,
QBrush, QTextCursor, QFont
import matplotlib.pyplot as plt
#plt.style.use('ggplot')
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
import seaborn as sns
iconroot = os.path.dirname(__file__)
class mywindow(QMainWindow):
def __init__(self):
super(mywindow, self).__init__()
self.setMinimumSize(QSize(1200,800))
self.setWindowTitle('My Graphic Window')
centralWidget = QWidget(self)
self.setCentralWidget(centralWidget)
gridLayout = QGridLayout(self)
centralWidget.setLayout(gridLayout)
qtRectangle = self.frameGeometry()
centerPoint = QDesktopWidget().availableGeometry().center()
qtRectangle.moveCenter(centerPoint)
self.move(qtRectangle.topLeft())
imageroot = QFileInfo(__file__).absolutePath()
# Greate new action
newaction = QAction(QIcon(imageroot +'/images/new.png'), '&New', self)
newaction.setShortcut('Ctrl+N')
newaction.setStatusTip('New document')
newaction.triggered.connect(self.newCall)
# Greate menu bar and add action
menubar = self.menuBar()
filemenu = menubar.addMenu('&Test')
filemenu.addAction(newaction)
# Get current screen geometry
self.Screen = QtWidgets.QDesktopWidget().screenGeometry()
print(self.Screen, self.Screen.height(), self.Screen.width())
# def createToolbar(self):
self.filetoolbar = self.addToolBar('File')
self.filetoolbar.addAction(newaction)
self.topleftdockwindow()
self.toprightdockwindow()
def newCall(self):
print('New')
# Greate dockable subwindow.
def topleftdockwindow(self):
topleftwindow = QDockWidget ('Info',self)
# Stick window to left or right
topleftwindow.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.addDockWidget(Qt.TopDockWidgetArea, topleftwindow)
topleftwindow.setWidget(createtabwidget())
topleftwindow.resize( topleftwindow.minimumSize() )
bottomleftwindow = QDockWidget("Matplot",self)
bottomleftwindow.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.addDockWidget(Qt.BottomDockWidgetArea, bottomleftwindow)
bottomleftwindow.setWidget(createplotwidget())
self.setDockNestingEnabled(True)
topleftwindow.resize( topleftwindow.minimumSize() )
self.splitDockWidget(topleftwindow, bottomleftwindow , Qt.Vertical)
#self.resizeDocks((topleftwindow, bottomleftwindow), (40,20),
#Qt.Horizontal)
# Greate topright dockwindow.
def toprightdockwindow(self):
toprightdock = QDockWidget ('Plot',self)
toprightdock = QDockWidget ('Plot',self)
toprightdock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.addDockWidget(Qt.TopDockWidgetArea, toprightdock)
#self.setDockOptions(self.AnimatedDocks | self.AllowNestedDocks)
toprightdock.setWidget(createpaintwidget())
toprightdock.setFloating( True )
bottomrightdock = QDockWidget("Technical report",self)
bottomrightdock.setAllowedAreas(Qt.LeftDockWidgetArea | Qt.RightDockWidgetArea)
self.addDockWidget(Qt.BottomDockWidgetArea, bottomrightdock)
bottomrightdock.setWidget(QtWidgets.QListWidget())
self.splitDockWidget(toprightdock, bottomrightdock, Qt.Vertical)
class createpaintwidget(QWidget):
def __init__(self):
super().__init__()
self.setBackgroundRole(QPalette.Base)
self.setAutoFillBackground(True)
self.sizeHint()
self.adjustSize()
def paintEvent(self, event):
self.pen = QPen()
self.brush = QBrush(Qt.gray,Qt.Dense7Pattern)
painter = QPainter(self)
painter.setPen(self.pen)
painter.setBrush(self.brush)
painter.drawRect(100,100,250,250)
painter.setBrush(QBrush())
painter.drawEllipse(400,100,200,200)
class createplotwidget(QWidget):
def __init__(self):
super().__init__()
self.initializewidget()
self.plot1()
self.setMaximumSize(self.sizeHint())
self.adjustSize()
def initializewidget(self):
self.setWindowTitle("Plotting M&N")
gridlayout = QGridLayout()
self.setLayout(gridlayout)
self.figure = plt.figure(figsize=(15,5))
self.canvas = FigureCanvas(self.figure)
self.toolbar = NavigationToolbar(self.canvas,self)
gridlayout.addWidget(self.canvas,1,0,1,2)
gridlayout.addWidget(self.toolbar,0,0,1,2)
def plot1(self):
# sns.set()
ax = self.figure.add_subplot(111)
x = [i for i in range(100)]
y = [i**2 for i in x]
ax.plot(x,y, 'b.-')
ax.set_title('Quadratic Plot')
self.canvas.draw()
class createtextdocument(QWidget):
def __init__(self):
super().__init__()
self.textedit()
def textedit(self):
self.textedit = QTextEdit()
self.cursor = self.textedit.textCursor()
class createtabwidget(QDialog):
def __init__(self):
super().__init__()
# Greate tabs in dockable window
tab = QTabWidget()
scroll = QScrollArea()
ncroll = QScrollArea()
mcroll = QScrollArea()
self.first = firsttabgeometry()
self.grid = Grid()
self.third = thirdtabloads()
scroll.setWidget(self.first)
ncroll.setWidget(self.grid)
mcroll.setWidget(self.third)
scroll.setWidgetResizable(True)
self.first.setMinimumSize(self.first.sizeHint())
self.grid.setMinimumSize(self.grid.sizeHint())
self.third.setMinimumSize(self.third.sizeHint())
self.adjustSize()
self.first.setMinimumSize(self.first.minimumSizeHint())
self.grid.setMinimumSize(self.grid.minimumSizeHint())
self.third.setMinimumSize(self.third.minimumSizeHint())
# Adding multiple tabslides
tab.addTab(self.first,'One')
tab.addTab(self.grid,'Two')
tab.addTab(self.third,'Three')
tab.setFont(QFont("Georgia",10,QFont.Normal))
vboxlayout = QVBoxLayout()
vboxlayout.addWidget(tab)
self.setLayout(vboxlayout)
class firsttabgeometry(QWidget):
def __init__(self):
super().__init__()
self.setFixedSize(self.sizeHint())
iconroot = QFileInfo(__file__).absolutePath()
font = QFont("Georgia",10,QFont.Normal)
# Add widget and buttons to tabs
sectiontypegroupbox = QGroupBox('&One',self)
sectiontypegroupbox.setFont(QFont("Georgia",10,QFont.Normal))
tab1button = QPushButton('')
tab1button.setIcon(QIcon(iconroot +'/images/circularcolumn'))
tab1button.setIconSize(QSize(60,60))
tab1button.clicked.connect(self.One)
squarebutton = QPushButton('')
squarebutton.setIcon(QIcon(iconroot +'/images/squarecolumn'))
squarebutton.setIconSize(QSize(60,60))
squarebutton.clicked.connect(self.Two)
wallbutton = QPushButton("")
wallbutton.setIcon(QIcon(iconroot +'/images/wall'))
wallbutton.setIconSize(QSize(60,60))
wallbutton.clicked.connect(self.Three)
circularlabel = QLabel(" One",self)
circularlabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
circularlabel.setFont(font)
sclabel = QLabel(" Two",self)
sclabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
sclabel.setFont(font)
walllabel = QLabel(" Three",self)
walllabel.setSizePolicy(QSizePolicy.Expanding,QSizePolicy.Expanding)
walllabel.setFont(font)
bottomgroupbox = QGroupBox("Group 2")
vboxlayout = QHBoxLayout()
vboxlayout.addStretch()
radiobutton2 = QRadioButton("Radio Button")
radiobutton3 = QRadioButton("Radio Button")
testbutton2 = QPushButton('Test Button 2')
vboxlayout.addWidget(radiobutton2)
vboxlayout.addWidget(radiobutton3)
vboxlayout.addWidget(testbutton2)
bottomgroupbox.setLayout(vboxlayout)
mainlayout = QGridLayout()
mainlayout.addWidget(tab1button,0,0)
mainlayout.addWidget(circularlabel,0,1)
mainlayout.addWidget(squarebutton,1,0)
mainlayout.addWidget(sclabel,1,1)
mainlayout.addWidget(wallbutton,2,0)
mainlayout.addWidget(walllabel,2,1)
mainlayout.setContentsMargins(200,50,50,50)
sectiontypegroupbox.setLayout(mainlayout)
gridlayout = QGridLayout()
gridlayout.addWidget(sectiontypegroupbox,1,0)
gridlayout.setContentsMargins(25,25,25,25)
self.setLayout(gridlayout)
def One(self):
print('One')
def Two(self):
print('Two')
def Three(self):
print('Three')
class FooWidget(QtWidgets.QWidget):
def __init__(self, path_icon, text, checked=False, parent=None):
super(FooWidget, self).__init__(parent)
lay = QtWidgets.QVBoxLayout(self)
pixmap = QtGui.QPixmap(os.path.join(iconroot, path_icon))
pixmap_label = QtWidgets.QLabel()
pixmap_label.resize(150, 150)
pixmap_label.setPixmap(pixmap.scaled(pixmap_label.size(), QtCore.Qt.KeepAspectRatio))
text_label = QtWidgets.QLabel(text)
checkbox = QtWidgets.QCheckBox(checked=checked)
lay.addWidget(pixmap_label)
lay.addWidget(text_label)
lay.addWidget(checkbox)
class Grid(QtWidgets.QWidget):
def __init__(self, parent=None):
super(Grid, self).__init__(parent)
self.setFixedSize(self.sizeHint())
font = QFont("Georgia",8,QFont.Normal)
lay = QtWidgets.QHBoxLayout(self)
icons = ["images/fixed-fixed.png",
"images/pinned-pinned.png",
"images/fixed-free.png",
"images/fixed-pinned.png"]
texts = ["Ley = 1.0 L\nLec = 1.0 L",
"Ley = 0.699 L\nLec = 0.699 L",
"Ley = 2.0 L\nLec = 2.0 L",
"Ley = 0.5 L\nLec = 0.5 L"]
for path_icon, text in zip(icons, texts):
w = FooWidget(os.path.join(iconroot, path_icon), text)
lay.addWidget(w)
class thirdtabloads(QtWidgets.QWidget):
def __init__(self, parent=None):
super(thirdtabloads, self).__init__(parent)
self.adjustSize()
table = loadtable()
add_button = QtWidgets.QPushButton("Add")
add_button.clicked.connect(table._addrow)
delete_button = QtWidgets.QPushButton("Delete")
delete_button.clicked.connect(table._removerow)
copy_button = QtWidgets.QPushButton("Copy")
copy_button.clicked.connect(table._copyrow)
button_layout = QtWidgets.QVBoxLayout()
button_layout.addWidget(add_button, alignment=QtCore.Qt.AlignBottom)
button_layout.addWidget(delete_button, alignment=QtCore.Qt.AlignTop)
button_layout.addWidget(copy_button, alignment=QtCore.Qt.AlignTop )
tablehbox = QtWidgets.QHBoxLayout()
tablehbox.setContentsMargins(10,10,10,10)
tablehbox.addWidget(table)
grid = QtWidgets.QGridLayout(self)
grid.addLayout(button_layout, 0, 1)
grid.addLayout(tablehbox, 0, 0)
def copy_widget(w):
if isinstance(w, QtWidgets.QWidget):
new_w = type(w)()
if isinstance(w, QtWidgets.QComboBox):
vals = [w.itemText(ix) for ix in range(w.count())]
new_w.addItems(vals)
return new_w
class loadtable(QtWidgets.QTableWidget):
def __init__(self, parent=None):
super(loadtable, self).__init__(1, 5, parent)
self.setFont(QtGui.QFont("Helvetica", 10, QtGui.QFont.Normal, italic=False))
headertitle = ("Load Name","N [kN]","My [kNm]","Mz [kNm]","Load Type")
self.setHorizontalHeaderLabels(headertitle)
self.verticalHeader().hide()
self.horizontalHeader().setHighlightSections(False)
self.horizontalHeader().setSectionResizeMode(QtWidgets.QHeaderView.Fixed)
self.setSelectionMode(QtWidgets.QAbstractItemView.NoSelection)
self.setColumnWidth(0, 130)
combox_lay = QtWidgets.QComboBox(self)
combox_lay.addItems(["ULS","SLS"])
self.setCellWidget(0, 4, combox_lay)
self.cellChanged.connect(self._cellclicked)
#QtCore.pyqtSlot(int, int)
def _cellclicked(self, r, c):
it = self.item(r, c)
it.setTextAlignment(QtCore.Qt.AlignCenter)
#QtCore.pyqtSlot()
def _addrow(self):
rowcount = self.rowCount()
self.insertRow(rowcount)
combox_add = QtWidgets.QComboBox(self)
combox_add.addItems(["ULS","SLS"])
self.setCellWidget(rowcount, 4, combox_add)
#QtCore.pyqtSlot()
def _removerow(self):
if self.rowCount() > 0:
self.removeRow(self.rowCount()-1)
#QtCore.pyqtSlot()
def _copyrow(self):
r = self.currentRow()
if 0 <= r < self.rowCount():
cells = {"items": [], "widgets": []}
for i in range(self.columnCount()):
it = self.item(r, i)
if it:
cells["items"].append((i, it.clone()))
w = self.cellWidget(r, i)
if w:
cells["widgets"].append((i, copy_widget(w)))
self.copy(cells, r+1)
def copy(self, cells, r):
self.insertRow(r)
for i, it in cells["items"]:
self.setItem(r, i, it)
for i, w in cells["widgets"]:
self.setCellWidget(r, i, w)
if __name__ == '__main__':
app = QtWidgets.QApplication(sys.argv)
app.setStyle("Fusion")
mainWin = mywindow()
mainWin.show()
mainWin.showMaximized()
sys.exit(app.exec_())
I would appreciate much any help on this.
If floating windows aren't essential to your tool then you can try dropping QDockWidget and using a series of QSplitter instead. This way you can have your nice box layout while having tabs to resize horizontally and vertically, and still resizing properly when the tool as a whole resizes.
My example is in PySide2, but you'll probably need to do very minor tweaks to PyQt5 (probably just the import names):
from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets
class SubWindow(QtWidgets.QWidget):
def __init__(self, label, parent=None):
super(SubWindow, self).__init__(parent)
self.label = QtWidgets.QLabel(label, parent=self)
self.label.setAlignment(QtCore.Qt.AlignCenter)
self.label.setStyleSheet("QLabel {font-size:40px;}")
self.main_layout = QtWidgets.QVBoxLayout()
self.main_layout.addWidget(self.label)
self.setLayout(self.main_layout)
class MainWindow(QtWidgets.QWidget):
def __init__(self, parent=None):
super(MainWindow, self).__init__(parent)
self.sub_win_1 = SubWindow("1", parent=self)
self.sub_win_2 = SubWindow("2", parent=self)
self.sub_win_3 = SubWindow("3", parent=self)
self.sub_win_4 = SubWindow("4", parent=self)
self.sub_splitter_1 = QtWidgets.QSplitter(QtCore.Qt.Horizontal, parent=self)
self.sub_splitter_1.addWidget(self.sub_win_1)
self.sub_splitter_1.addWidget(self.sub_win_2)
self.sub_splitter_2 = QtWidgets.QSplitter(QtCore.Qt.Horizontal, parent=self)
self.sub_splitter_2.addWidget(self.sub_win_3)
self.sub_splitter_2.addWidget(self.sub_win_4)
self.splitter = QtWidgets.QSplitter(QtCore.Qt.Vertical, parent=self)
self.splitter.addWidget(self.sub_splitter_1)
self.splitter.addWidget(self.sub_splitter_2)
self.main_layout = QtWidgets.QVBoxLayout()
self.main_layout.addWidget(self.splitter)
self.setLayout(self.main_layout)
self.setWindowTitle("Layout example")
self.resize(500, 500)
inst = MainWindow()
inst.show()
This gives you something like this:
Right now the top/bottom horizontal splitters function separately, but you can easily tie them together with an event.
Hope that helps!
I have already read some answers but they do not work for me.
This is my code:
from PyQt5.QtWidgets import QWidget, QCheckBox, QApplication, QHBoxLayout, QLabel
from PyQt5.QtCore import Qt
from PyQt5.QtGui import QPixmap
import sys
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
cbAll = QCheckBox('Slice 1', self) # Slice 1
cbAll.move(1200, 130)
cbAll.toggle()
cbAll.stateChanged.connect(self.OpenSlice1)
self.setGeometry(0, 25, 1365, 700)
self.setWindowTitle('Original Slices')
self.show()
def OpenSlice1(self,state):
pixmap = QPixmap("E:\BEATSON_PROJECT\python\GUI\home.png")
self.lbl = QLabel(self) #Qlabel used to display QPixmap
self.lbl.setPixmap(pixmap)
if state == Qt.Checked:
self.lbl.show()
else:
self.lbl.hide()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
However when it goes into the unchecked option it does not hide the image:
Original window:
Checked Slice 1 window:
From this point on it always shows the image and I want it to hide it. i.e unckecking the box does not work:
The problem is caused because each time you press you are creating a new QLabel and you assign the same variable so you lose access to that element, and then you are closing the new QLabel, but not the old one. What you must do is create it and only hide it for it you could use the setVisible() or hide() and show() method.
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
cbAll = QCheckBox('Slice 1', self) # Slice 1
cbAll.move(1200, 130)
cbAll.toggle()
cbAll.stateChanged.connect(self.OpenSlice1)
pixmap = QPixmap("E:\BEATSON_PROJECT\python\GUI\home.png")
self.lbl = QLabel(self) #Qlabel used to display QPixmap
self.lbl.setPixmap(pixmap)
self.setGeometry(0, 25, 1365, 700)
self.setWindowTitle('Original Slices')
self.show()
def OpenSlice1(self, state):
self.lbl.setVisible(state != Qt.Unchecked)
# or
"""if state == Qt.Checked:
self.lbl.show()
else:
self.lbl.hide()"""
I have been studying PyQt5 and recenlty decided to make a gui for a simple chat client. This is my mockup:
I used QGridLayout, and this is what I got:
How do I decrease the size of the bottom QTextEdit, so it has 2-3 available lines, and make QPushButton larger?
My program:
import sys
from PyQt5.QtWidgets import (QMainWindow, QAction, QApplication, QDesktopWidget,
QDialog, QTextEdit, QGridLayout, QPushButton, QWidget)
from PyQt5.QtGui import QIcon
class Chat(QMainWindow):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
self.populateUI()
self.resize(400, 400)
self.center()
self.setWindowTitle('Simple Chat')
self.show()
def center(self):
qr = self.frameGeometry()
cp = QDesktopWidget().availableGeometry().center()
qr.moveCenter(cp)
self.move(qr.topLeft())
def populateUI(self):
self.createMenu()
self.statusBar()
centralWidget = CentralWidget()
self.setCentralWidget(centralWidget)
def createMenu(self):
menuBar = self.menuBar()
fileMenu = menuBar.addMenu('&File')
fileMenu.addAction(self.createExitAction())
helpMenu = menuBar.addMenu('&Help')
helpMenu.addAction(self.createAboutAction())
def createExitAction(self):
exitAction = QAction(QIcon('exit.png'), '&Exit', self)
exitAction.setShortcut('Ctrl+Q')
exitAction.setStatusTip('Exit application')
exitAction.triggered.connect(self.close)
return exitAction
def createAboutAction(self):
aboutAction = QAction(QIcon('info.png'), '&About', self)
aboutAction.setShortcut('Ctrl+H')
aboutAction.setStatusTip('Information about the program')
aboutAction.triggered.connect(self.createAboutDialog)
return aboutAction
def createAboutDialog(self):
dialog = QDialog(self)
dialog.setWindowTitle('About')
dialog.setWindowIcon(QIcon('info.png'))
dialog.resize(200, 200)
dialog.exec_()
class CentralWidget(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
ribbon = QTextEdit()
chat = QTextEdit()
sendBtn = QPushButton('Send')
grid = QGridLayout()
grid.setSpacing(3)
grid.addWidget(ribbon, 0, 0, 1, 3)
grid.addWidget(chat, 1, 0, 1, 1)
grid.addWidget(sendBtn, 1, 2)
self.setLayout(grid)
if __name__ == '__main__':
app = QApplication(sys.argv)
chat = Chat()
sys.exit(app.exec_())
You first need to set a fixed height for the bottom text-edit based on the number of lines you want shown. This also needs to take account of the frame and document margin:
def initUI(self):
...
chat.setFixedHeight(
(chat.fontMetrics().lineSpacing() * 3) +
(chat.document().documentMargin() * 2) +
(chat.frameWidth() * 2) - 1
)
You then need to change the size policy of the button so that it expands vertically:
policy = sendBtn.sizePolicy()
policy.setVerticalPolicy(QSizePolicy.MinimumExpanding)
sendBtn.setSizePolicy(policy)
Finally, you need to set the stretch factors on the first row and column so that the text-edits take up all the available space:
grid.setRowStretch(0, 1)
grid.setColumnStretch(0, 1)
I guess you are looking after setFixedSize(QSize size) of QWidget.