PyQt QScrollArea no scrollarea - python

I have
class View(QtWidgets.QLabel):
def __init__(self):
super(View,self).__init__()
self.cropLabel = QtWidgets.QLabel(self)
self.label = QtWidgets.QLabel(self)
self.ogpixmap = QtGui.QPixmap()
fileName = r'C:/Users/user11.HPO-SAMAT/Pictures/Lake.jpg'
image = QtGui.QImage(fileName)
self.pixmap = QtGui.QPixmap.fromImage(image)
self.label.setPixmap(self.pixmap)
self.label.adjustSize()
and then I call this class:
class Viewer(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.view = View()
self.scroller = QtWidgets.QScrollArea()
self.scroller.setWidget(self.view)
self.scroller.setWidgetResizable(True)
self.scroller.adjustSize()
But QScrollArea does not seem to work (noscrollbar though the image is visible and I can expand QMainWindows to see it entirely)
What am I doing wrong ?

I do not understand so they put several labels inside View, if we remove the labels that are other we get what you want.
class View(QtWidgets.QLabel):
def __init__(self, parent=None):
super(View,self).__init__(parent)
fileName = "/home/qhipa/Pictures/1475777628875.jpg"
self.pixmap = QtGui.QPixmap(fileName)
self.setPixmap(self.pixmap)
class Viewer(QtWidgets.QMainWindow):
def __init__(self):
super().__init__()
self.view = View(self)
self.scroller = QtWidgets.QScrollArea(self)
self.setCentralWidget(self.scroller)
self.scroller.setWidget(self.view)
self.scroller.setWidgetResizable(True)
self.scroller.adjustSize()
Instead if you want to get several labels, it is better that the View class inherits from QWidget.
class View(QtWidgets.QWidget):
def __init__(self, parent=None):
super(View,self).__init__(parent)
self.setLayout(QtWidgets.QVBoxLayout())
self.cropLabel = QtWidgets.QLabel(self)
self.label = QtWidgets.QLabel(self)
self.layout().addWidget(self.cropLabel)
self.layout().addWidget(self.label)
self.pixmap = QtGui.QPixmap("/home/qhipa/Pictures/1475777628875.jpg")
self.label.setPixmap(self.pixmap)
self.label.adjustSize()

Related

Qt - Python - Write to label from main class

Below is part of my code. I would like to set the label (marked by an arrow) to the value returned by the function executed in the main class. my code returns AttributeError: type object 'MainTab' has no attribute 'label'
class App(QMainWindow):
def __init__(self):
super().__init__()
self.setMinimumSize(800, 500)
self.tab_widget = TabWidget(self)
self.setCentralWidget(self.tab_widget)
self.show()
class TabWidget(QWidget):
def __init__(self, parent):
super(QWidget, self).__init__(parent)
self.layout = QVBoxLayout(self)
self.tabs = QTabWidget()
self.tabs.addTab(MainTab(), "Main")
self.tabs.resize(500, 200)
# Add tabs to widget
self.layout.addWidget(self.tabs)
self.setLayout(self.layout)
class MainTab(QDialog):
def __init__(self, parent=None):
super().__init__()
self.originalPalette = QApplication.palette()
self.mainLayout = QHBoxLayout()
self.buttonLayout = QVBoxLayout()
buttonMsg = QPushButton("test button")
self.buttonLayout.addWidget(buttonMsg)
self.mainLayout.addLayout(self.buttonLayout)
self.label = QLabel(self) # <--------------------------------------------
# pixmap = QPixmap('test.jpg')
# self.label.setPixmap(pixmap)
self.label.setStyleSheet("border: 1px solid black;")
self.label.setAlignment(Qt.AlignCenter)
self.mainLayout.addWidget(self.label)
self.setLayout(self.mainLayout)
def main():
check_requirements(exclude=('tensorboard', 'thop'))
im0 = yoloRun.run()
height, width, channel = im0.shape
bytesPerLine = 3 * width
qImg = QImage(im0.data, width, height, bytesPerLine, QImage.Format_RGB888)
pixmap = QPixmap(qImg)
MainTab.label.setPixmap(pixmap) # <--------- FROM HERE I WOULD LIKE TO PUT PIXMAP AS BACKGROUND
if __name__ == '__main__':
t1 = threading.Thread(target=main)
t1.start()
app = QApplication([])
app.setStyle('Fusion')
app.setApplicationName('KiTest')
ex = App()
app.exec()
How am I supposed to do this?

Mutual resizing of widgets

I'm implementing an application, where a side widget can expand/shrink, so an another widget must shrink/expand. (Or the side widget can be shown over that widget, it doesn't matter, I accept both implementations). It can looks like that:
Here is a part of my code:
class AppView:
def __init__(self):
self._mainWindow = QDialog(None)
self._schedule = ScheduleView(self._mainWindow)
self._schedule.setMinimumWidth(25)
self._schedule.setMaximumWidth(250)
self._tutorial = TutorialView(self._mainWindow)
self._schedule.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Expanding)
self._tutorial.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)
layout = QHBoxLayout()
layout.addWidget(self._schedule)
layout.addWidget(self._tutorial)
layout.setSpacing(0)
layout.setContentsMargins(0, 0, 0, 1)
self._mainWindow.setLayout(layout)
class TutorialView(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
self._presenter = TutorialPresenter(self)
self.reqReprSections.connect(self.setModel)
self.reqReprTopics.connect(self.setModel)
self._widget = QQuickWidget(self)
self._widget.rootContext().setContextProperty('tutorialView', self)
self._widget.setSource(QUrl('modules/manual/manualForm/TutorialForm.qml'))
class ScheduleView(QWidget):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
self._presenter = SchedulePresenter(self)
self._widget = QQuickWidget(self)
self._widget.setResizeMode(QQuickWidget.SizeViewToRootObject)
self._widget.rootContext().setContextProperty('scheduleView', self)
self._widget.rootContext().setContextProperty('groupsModel', self)
self._widget.setSource(QUrl('modules/schedule/scheduleForm/ScheduleForm.qml'))
How can I do such resizes in code?
To get that behavior you can use a QHBoxLayout by embedding a rotated button in the middle of the side widgets. You must change the left widget's size policy so that it does not expand.
To implement the rotated button you must override the paintEvent method, in addition to modifying the size policy so that it expands vertically and not horizontally.
class ShrinkExpandButton(QPushButton):
def __init__(self, *args, **kwargs):
QPushButton.__init__(self, *args, **kwargs)
self.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding)
self.setFixedWidth(2*self.fontMetrics().height())
def paintEvent(self, event):
painter = QStylePainter(self)
painter.rotate(-90)
painter.translate(-self.height(), 0)
option = QStyleOptionButton()
self.initStyleOption(option)
size = option.rect.size()
size.transpose()
option.rect.setSize(size)
painter.drawControl(QStyle.CE_PushButton, option)
class ShrinkExpandWidget(QWidget):
def __init__(self, leftWidget, rightWiget, text, parent=None):
QWidget.__init__(self, parent)
button = ShrinkExpandButton(text, self)
self.setLayout(QHBoxLayout())
self.layout().setSpacing(0)
self.layout().addWidget(leftWidget)
self.layout().addWidget(button)
self.layout().addWidget(rightWiget)
leftWidget.setSizePolicy(QSizePolicy.Maximum, QSizePolicy.Expanding)
button.clicked.connect(lambda: leftWidget.setVisible(not leftWidget.isVisible()))
Example:
if __name__ == '__main__':
import sys
app = QApplication(sys.argv)
listWidget = QListWidget()
for i in range(20):
listWidget.addItem("{}".format(i))
tableWidget = QTableWidget()
tableWidget.setColumnCount(10)
tableWidget.setRowCount(20)
for i in range(tableWidget.rowCount()):
for j in range(tableWidget.columnCount()):
tableWidget.setItem(i, j, QTableWidgetItem("({}, {})".format(i, j)))
listWidget.setFixedWidth(240)
w = ShrinkExpandWidget(listWidget, tableWidget, "Shrink - Expand")
w.resize(720, 480)
w.show()
sys.exit(app.exec_())
Output:

PyQt5: widget not displayed after being added to layout

The task is to write a robot emulator. I have three classes in my code: ControlWidget, BoardWidget and Emulator (the main widget that should combine Control and Board in one window). I'm going to draw some pictures on the BoardWidget with the use of QPainter.
class ControlWidget(QFrame):
def __init__(self):
super().__init__()
self._vbox_main = QVBoxLayout()
self.initUI()
def initUI(self):
# ... adding some buttons
self.setLayout(self._vbox_main)
self.setGeometry(50, 50, 600, 600)
self.setWindowTitle('Robot Controller')
class BoardWidget(QWidget):
def __init__(self):
super().__init__()
self._robot_pixmap = QPixmap("robo.png")
self.initUI()
def initUI(self):
self.setStyleSheet("QWidget { background: #123456 }")
self.setFixedSize(300, 300)
self.setWindowTitle("Robot Emulator")
Both of them appear nicely if shown in different windows:
class Emulator(QWidget):
def __init__(self):
super().__init__()
self._control = ControlWidget()
self._board = BoardWidget()
self._board.show()
self._control.show()
But the magic comes here. I want my Emulator show both the board and control:
class Emulator(QWidget):
def __init__(self):
super().__init__()
self._control = ControlWidget()
self._board = BoardWidget()
self.initUI()
self.show()
def initUI(self):
layout = QBoxLayout(QBoxLayout.RightToLeft, self)
layout.addWidget(self._control)
layout.addStretch(1)
layout.addWidget(self._board)
self.setLayout(layout)
self.setWindowTitle('Robot Emulator')
self.setWindowIcon(QIcon("./assets/robo.png"))
# self._board.update()
I've killed three hours trying to fix it. I've tried to present my board as a QPixmap over the QLabel inside the QBoxLayout. I tried to replace QBoxLayout with the QHBoxLayout. Nothing makes any difference.
As #ekhumoro stated in the comments, it is necessary to add the QPixmap to a QLabel and then set it on the BoardWidget layout manager with setLayout() function.
One solution could be the next reimplementation of BoardWidget class:
class BoardWidget(QWidget):
def __init__(self):
super().__init__()
self._robot_pixmap = QPixmap("robo.png")
self.label = QLabel()
self.label.setPixmap(self._robot_pixmap)
self._vbox_board = QVBoxLayout()
self.initUI()
def initUI(self):
self._vbox_board.addWidget(self.label)
self.setLayout(self._vbox_board)
self.setStyleSheet("QWidget { background: #123456 }")
self.setFixedSize(300, 300)
self.setWindowTitle("Robot Emulator")
The result is shown here:

giving index to QLineEdit

i want to give index for QLineEdit's.
i have this code.
from PyQt4 import QtGui, QtCore
import sys
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__(parent)
# main button
self.addButton = QtGui.QPushButton('button to add other widgets')
self.addButton.clicked.connect(self.addWidget)
self.savebutton = QtGui.QPushButton('Save')
# scroll area widget contents - layout
self.scrollLayout = QtGui.QFormLayout()
# scroll area widget contents
self.scrollWidget = QtGui.QWidget()
self.scrollWidget.setLayout(self.scrollLayout)
# scroll area
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setWidget(self.scrollWidget)
# main layout
self.mainLayout = QtGui.QVBoxLayout()
# add all main to the main vLayout
self.mainLayout.addWidget(self.addButton)
self.mainLayout.addWidget(self.scrollArea)
self.mainLayout.addWidget(self.savebutton)
# central widget
self.centralWidget = QtGui.QWidget()
self.centralWidget.setLayout(self.mainLayout)
# set central widget
self.setCentralWidget(self.centralWidget)
def addWidget(self):
self.scrollLayout.addRow(Test())
class Test(QtGui.QWidget):
def __init__( self, parent=None):
super(Test, self).__init__(parent)
self.kod = QtGui.QLineEdit()
layout = QtGui.QHBoxLayout()
layout.addWidget(self.kod)
self.setLayout(layout)
app = QtGui.QApplication(sys.argv)
myWidget = Main()
myWidget.show()
app.exec_()
when i clicked save button, savebutton sends just last QLineEdit widget.
image is here
like in this photo, i want self.kod[0].text()="aaaa" self.kod1="bbbb" self.kod[2]="cccc" and it just will go like this. kod[x] this x number will increase automatically, while i click add widgetbutton. or it can be like this: kod1,kod2,kod3, kodx. it doesnt matter, i want to just differ from eacht other and take text from them.
You can set a list in Main class, like this ['aaa', 'bbb', 'ccc'],
and set a var = 0.
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__(parent)
#
self.lineText = ['aaa', 'bbb', 'ccc']
self.var = 0
...
def addWidget(self):
self.scrollLayout.addRow(Test(self, self.var))
self.var += 1
Then give Test class an arg,
class Test(QtGui.QWidget):
def __init__( self, parent=None, count):
super(Test, self).__init__(parent)
#
self.parent = parent
self.kod = QtGui.QLineEdit()
#
self.kod.setText(self.parent.lineText[count])
---
class Main(QtGui.QMainWindow):
def __init__(self, parent = None):
super(Main, self).__init__(parent)
self.kod = []
...
def addWidget(self):
temp = Test()
self.kod.append(temp)
self.scrollLayout.addRow(temp)
and print(self.kod)
[<__main__.Test object at 0x00000000032EEC18>, <__main__.Test object at 0x00000000032EEDC8>, <__main__.Test object at 0x00000000032EEF78>]

How can I pass data in run method (thread) (python, Pyqt)

I want to make the thread, in the window, using PyQt(Python). For example
class window(QtGui.QWidget):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(100, 100, 500, 200)
self.setWindowTitle('Hello')
self.label = QtGui.QLabel(u'WoRLd', self)
self.Layout = QtGui.QVBoxLayout()
self.Layout.addWidget(self.label)
self.setLayout(self.Layout)
self.introduced = 123
self.request = Requests()
self.request.start()
self.connect(self.request, QtCore.SIGNAL("mysignal(QString)"),
self.on_change, QtCore.Qt.QueuedConnection)
def on_change(self, s):
self.label.setText(s)
class Requests():
def __init__(self, parent=None):
QtCore.QThread.__init__(self, parent)
def run(self):
self.emit(QtCore.SIGNAL("mysignal(QString)"), "143242" )
app = QtGui.QApplication(sys.argv)
main = window()
main.show()
sys.exit(app.exec_())
But, in method "run", I need some dates from "class window" (variable: introduced).
How can I pass this variable to "def run"?
you just have to make arguments for it and pass it into the class instance. then assign it to self.date, this makes it accesible across the class instance:
class window(QtGui.QWidget):
def __init__(self, parent = None):
QtGui.QWidget.__init__(self, parent)
self.setGeometry(100, 100, 500, 200)
self.setWindowTitle('Hello')
self.label = QtGui.QLabel(u'WoRLd', self)
self.Layout = QtGui.QVBoxLayout()
self.Layout.addWidget(self.label)
self.setLayout(self.Layout)
self.introduced = 123
date = # get some date whatever you need to pass here
self.request = Requests(date)
self.request.start()
self.connect(self.request, QtCore.SIGNAL("mysignal(QString)"),
self.on_change, QtCore.Qt.QueuedConnection)
def on_change(self, s):
self.label.setText(s)
class Requests():
def __init__(self, date, parent=None):
self.date = date
QtCore.QThread.__init__(self, parent)
def run(self):
# do something with self.date here
self.emit(QtCore.SIGNAL("mysignal(QString)"), "143242" )
app = QtGui.QApplication(sys.argv)
main = window()
main.show()
sys.exit(app.exec_())

Categories