The issue that I'm facing is when I want to split the functionality of the menubar into multiple files (classes), each of them specific for handling options (File/Help/Edit and so on).
In the Main UI class I have:
class MyFrame(QMainWindow):
def __init__(self):
super().__init__()
self.menu_bar = self.menuBar()
# Create menu
self.add_menu()
def add_menu(self):
help_menu = MenuHelp(self)
def getMenuBar(self):
return self.menu_bar
In the MenuHelp (class):
class MenuHelp(QMenu):
def __init__(self, parrent_widget):
super(MenuHelp, self).__init__()
self.menu_variable = parrent_widget.getMenuBar().addMenu('Help')
about_action = self.menu_variable.addAction('About')
about_action.setStatusTip('About')
about_action.triggered.connect(self.handle_trigger)
def handle_trigger(self):
print('Im here')
The menubar is correctly shown, but handle_trigger method is never called, any ideas on what am I doing wrong?
You must pass a parent to your QMenu. You must change:
class MenuHelp(QMenu):
def __init__(self, parrent_widget):
super(MenuHelp, self).__init__()
to:
class MenuHelp(QMenu):
def __init__(self, parrent_widget):
super(MenuHelp, self).__init__(parrent_widget)
Related
When I am trying to reference in a different class in a function I get a error saying their is not attribute between the widget I am referencing and the class. Here is the code displaying the referencing:
class Window(tk.Tk):
def __init__(self):
super().__init__()
self.init_csv()
def init_csv(self):
LeftFrame.spellings_listbox.insert(tk.END,i)
class LeftFrame(tk.Frame):
def __init__(self, container):
super().__init__(container,width=400,height=600,bg="red")
self.pack(side=tk.LEFT)
self.pack_propagate(0)
self.widgets()
def widgets(self):
self.spellings_listbox = tk.Listbox(self)
self.spellings_listbox.pack(expand=True,fill=tk.BOTH,side=tk.BOTTOM)
You have to create an instance of the LeftFrame class before you can use it or the widgets inside. This isn't something unique to tkinter, it's a fundamental aspect of using classes.
Usually the solution looks something like this:
class Window(tk.Tk):
def __init__(self):
super().__init__()
self.init_csv()
self.left_frame = LeftFrame(self)
def init_csv(self):
self.left_frame.spellings_listbox.insert(tk.END,i)
This is the current code I am using:
class Opening(QDialog):
def __init__(self):
super(Opening, self).__init__()
loadUi("reminder2.ui", self)
self.startbutton.clicked.connect(self.gotomain)
def gotomain(self):
main = MainWindow()
widget.addWidget(main)
widget.setCurrentIndex(widget.currentIndex()+1)
class MainWindow(QDialog):
def __init__(self):
super(MainWindow, self).__init__()
loadUi("reminder.ui",self)
self.typebutton.clicked.connect(self.med)
self.searchbutton.clicked.connect(self.medd)
self.med2.hide()
self.med3.hide()
self.med4.hide()
self.med5.hide()
self.med6.hide()
self.med7.hide()
self.med8.hide()
self.addbutton.clicked.connect(self.clickAdd)
def med(self):
self.stackedWidget.setCurrentWidget(self.typemed)
def medd(self):
self.stackedWidget.setCurrentWidget(self.searchmed)
def clickAdd(self):
self.med2.show()
I'm trying to create a set of PySide classes that inherit QWidget, QMainWindow, and QDialog. Also, I would like to inherit another class to overrides a few functions, and also set the layout of the widget.
Example:
Mixin:
class Mixin(object):
def __init__(self, parent, arg):
self.arg = arg
self.parent = parent
# Setup the UI from QDesigner
ui = Ui_widget()
ui.setupUi(self.parent)
def setLayout(self, layout, title):
self.parent.setWindowTitle(title)
self.parent.setLayout(layout)
def doSomething(self):
# Do something awesome.
pass
Widget:
class Widget(Mixin, QtGui.QWidget):
def __init__(self, parent, arg):
super(Widget, self).__init__(parent=parent, arg=arg)
This won't work, but doing this through composition works
Widget (Composition):
class Widget(QtGui.QWidget):
def __init__(self, parent, arg):
super(Widget, self).__init__(parent=parent)
mixin = Mixin(parent=self, arg=arg)
self.setLayout = mixin.setLayout
self.doSomething = mixin.doSomething
I would like to try to have the widget inherit everything instead of having part of it done through composition. Thanks!
Keep class Widget(Mixin, QtGui.Widget):, but add a super call in Mixin.__init__. This should ensure the __init__ method of both Mixin and QWidget are called, and that the Mixin implementation of the setLayout method is found first in the MRO for Widget.
class Mixin(object):
def __init__(self, parent=None, arg=None):
super(Mixin, self).__init__(parent=parent) # This will call QWidget.__init__
self.arg = arg
self.parent = parent
# Setup the UI from QDesigner
ui = Ui_widget()
ui.setupUi(self.parent)
def setLayout(self, layout, title):
self.parent.setWindowTitle(title)
self.parent.setLayout(layout)
def doSomething(self):
# Do something awesome.
pass
class Widget(Mixin, QtGui.QWidget):
def __init__(self, parent, arg):
super(Widget, self).__init__(parent=parent, arg=arg) # Calls Mixin.__init__
I'm trying to make a custom widget getting more and more descriptive with each sub class. For instance below, I'm adding to a list of boxes as I make them. I want do_stuff() to only run once but I want it to run on initialization. My problem is that I need all of the __setupUi() functions to run before I finish it. Any help is appreciated.
from PyQt5 import QtCore, QtWidgets
class layer4:
def __init__(self):
self.boxes = []
self.__setupUi()
# I want to run this once AFTER all of the children (regardless of how deep it goes) have run
self.do_stuff()
def __setupUi(self):
self.qsb = QtWidgets.QSpinBox()
self.boxes.append(self.qsb)
def do_stuff(self):
print(self.boxes)
class layer3(layer4):
def __init__(self):
super().__init__()
self.__setupUi()
def __setupUi(self):
self.qsb2 = QtWidgets.QSpinBox()
self.boxes.append(self.qsb2)
class layer2(layer3):
def __init__(self):
super().__init__()
self.__setupUi()
def __setupUi(self):
self.datetimebox = QtWidgets.QDateTimeEdit()
self.boxes.append(self.datetimebox)
class layer1(layer2):
def __init__(self):
super().__init__()
self.__setupUi()
def __setupUi(self):
self.other = QtWidgets.QDateTimeEdit()
self.boxes.append(self.other)
So if I run
t = layer2()
It should return 2 QSpinboxes and 1 datetimeedit
I am lost with all the parenting/initialising issues and have no idea why this does not work.
So I create a Label, then I create another Label with some painting in it, them I make a widget that contains the two, then I would like to put this new widget inside the main window... but nothing appears
import sys
import os
from PyQt5.QtWidgets import *
from PyQt5.QtCore import *
class Labhtml(QLabel):
def __init__(self):
super().__init__()
label = QLabel('html')
class Bar(QLabel):
def __init__(self):
super().__init__()
self.resize(100, 5)
def paintEvent(self, e):
qp = QPainter(self)
qp.setBrush(QColor(200, 0, 0))
qp.drawRect(0,0,200,3)
class Wid(QWidget):
def __init__(self, parent):
super().__init__(parent=parent)
widget = QWidget()
html = Labhtml()
bar = Bar()
self.layout = QVBoxLayout(widget)
self.layout.addWidget(html)
self.layout.addWidget(bar)
class Example(QScrollArea):
def __init__(self):
super().__init__()
widget = QWidget()
layout = QVBoxLayout(widget)
layout.addWidget(Wid(widget))
self.setWidget(widget)
self.setWidgetResizable(True)
self.show()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())
First for the class Labhtml, when you inherit from QLabel, you can use the methods and the attributes of the base class, or use the instantiation mechanism to pass some parameters :
class Labhtml(QLabel):
def __init__(self):
super().__init__()
self.setText('html')
Then you don't need to create another widget inside the Wid class, but you have to refer to self instead :
class Wid(QWidget):
def __init__(self, parent):
super().__init__(parent=parent)
html = Labhtml()
bar = Bar()
self.layout = QVBoxLayout(self)
self.layout.addWidget(html)
self.layout.addWidget(bar)
About the instantiation mechanism you could also write the classes by declaring a new text argument (the same used for the Qlabel), and pass it when you create your instance :
class Labhtml(QLabel):
def __init__(self, text):
super().__init__(text)
class Wid(QWidget):
def __init__(self, parent):
super().__init__(parent=parent)
html = Labhtml('html')