Tabs in different Files (as classes) with PyQt5 - python

I didn´t find a example to put the different tabs of QTabWidget in different files. Just a Methode or as a new (child-)class. I´m a beginner in Python with QT and thought I can get a better overview if I put the different tabs in different classes.
I have the following class in a MainWindow:
class pages(QTabWidget):
def __init__(self, parent = None):
super(pages, self).__init__(parent)
#Variables
self.inputFile = 0
self.tab1 = QWidget()
self.tab2 = page2()
self.addTab(self.tab1,"Tab 1")
self.addTab(self.tab2,"Tab 2")
self.tab1UI()
#self.tab2UI()
self.setWindowTitle("tab demo")
(The commented tab2 I tried to get into another class which is called page2(). tab1UI ist still a method within the class pages.)
Furthermore, is it possible to Access variables in a tab in a child class to a parent one by super or something?

Related

python tkinter inside class - getting state of widgets

I've written a program and I'm learning about classes and thus, rewriting the code to take advantage of classes and objects.
My problem is if I create a tkinter widget "dropdown menu" from a class, I can not retrieve the get.state variable.
class ...:
def make_drop_menu(self,parent,drop_opts,drop='empty',state=''):
self.parent = parent
self.drop = drop
self.drop_opts = drop_opts
self.state = tk.StringVar()
self.state.set(self.drop_opts[0]) # sets default value on drop (drop down menu)
self.drop = OptionMenu(self.parent, self.state, *self.drop_opts) # completed drop
return self.drop
----------------
class main:
self.widget = self.var.make_drop_menu(self.obj_mainwindow.btm_frame, self.col_opts)
Added for clearity:
window = windowclass() #windowclass is the style for tkinter. Makes a tkwindow.
self.widget = self.windowclass.var.make_drop_Menu() #
I've left out some code to simplify. But my main problem is that I create a widget called self.widget which builds my drop down menu. However, I have NO idea how to get the state of the drop down.
Hopefully the code makes sense.
If your class is named MyClass, then to access the state variable you would use the instance of the class. In your case it appears that self.var is the instance of your class, so it would look something like this:
self.var = MyClass()
self.var.make_drop_menu(...)
...
print(self.var.state.get())
Made the make_drop_menu class independent of any other class object. That way I could make a drop menu, assign the parent tk window, and create a method for getting the state variable when called.
Thanks to Bryan Oakley for the help!

tkinter: How to access a StringVar and objects from a different class?

I'm having a simple tkinter two frame application with a Label, Entry and Button widget and I want to access a StringVar() of FrameOne with a Entry and Button of FrameTwo.
If have seen a lots of examples of code, but do not get how this is been done in my example below. Many programmers are using a controller. If I would use a controller, I end up from an error to another.
For example:
FirstFrame = FrameOne(mainWindow)`
TypeError: __init__() missing 1 required positional argument: 'controller'
Which I completely understand, because I do not pass anything into the new 'controller' class argument when calling the Frame class. But I do not know what I should pass into this to solve it. Perhaps it is also caused by the lack of knowledge of using class variables (any literature tips are welcome).
The same counts for the solution to inherit FrameOne into FrameTwo. I bump into the same amount of errors applying to my code.
Another thing is that many programmers have examples of two frames that are not visible at the same time, while in my example I have two frames underneath each other at the same time.
An different related issue that I have is, what if the label widget of FrameOne was a Text widget? How do I access the widget from FrameTwo.
I could make it work with globals, but I do not want to use such writing and I will keep the access widget problem anyhow.
Please find my code below:
import tkinter as tk
class AppWindow():
def __init__(self, master):
self.master = master
master.title("Test Application")
master.geometry("1060x680")
master.grid_propagate(False)
class FrameOne(tk.Frame):
def __init__(self, parent):
super().__init__()
self["borderwidth"]=5
self["relief"]="ridge"
self.LabelText = tk.StringVar()
self.LabelText.set("It is not working yet")
self.testlabel = tk.Label(self, textvariable=self.LabelText)
self.testlabel.grid(row=1, column=1)
class FrameTwo(tk.Frame):
def __init__(self, parent):
super().__init__()
self["borderwidth"]=5
self["relief"]="ridge"
self.testentry = tk.Entry(self)
self.testentry.insert("end", "This should be working")
self.testentry.grid(row=1,column=1)
self.testbutton = tk.Button(self, text="Test the label", command=self.updatelabel)
self.testbutton.grid(row=1,column=2)
def updatelabel(self):
FrameOne.LabelText.set(self.testentry.get()) #HOW TO FIX THIS CODE THE RIGHT WAY?
#Create a window as defined in the AppWindow class
mainWindow = AppWindow(tk.Tk())
#Create a Frame as defined in class FrameOne
FirstFrame = FrameOne(mainWindow)
FirstFrame.grid(row=0, column=0) #Positioning Frame on Window
#Create a Frame as defined in class FrameOne
SecondFrame = FrameTwo(mainWindow)
SecondFrame.grid(row=1, column=0) #Positioning Frame on Window
Like with any python object, you access an attribute of an object using a reference to the object.
In your case, updatelabel should look like this:
def updatelabel(self):
FirstFrame.LabelText.set(self.testentry.get())
Note: your use of uppercase characters for instance variables makes your code much harder to comprehend. I recommend following the naming guidelines in PEP8.

Obtaining widget values in tkinter

How do I refer to the widget values in the following code.Here I have added widgets by calling methods in the app class for different frames.Next,I want to access the values in all the Widgets(which the user enters) of all the frames at the same time.But I am not able to figure out how should I refer to them and access their values!
class myapp():
def __init__(self,parent):
self.parent=parent
self.container=Frame(self.parent)
self.container.pack()
self.tab1=Button(self.container,text='tab1',command=self.tab1Click)
self.tab2=Button(self.container,text='tab*emphasized text*2',command=self.tab2Click)
self.tab1.pack()
self.tab2.pack()
def tab1Click(self):
top=Toplevel()
self.container1=Frame(top)
self.add_widget1(self.container1)#self.add_widgeti(parent) is a method in myapp() class to add a widget to a frame
self.add_widget2(self.container1)
self.add_widget3(self.container1)
self.container1.pack()
def tab2Click(self):
top=Toplevel()
self.container2=Frame(top)
self.add_widget2(self.container2)
self.add_widget4(self.container2)
self.add_widget5(self.container2)
self.container2.pack()
def write(self):
#here I want to write the values contained in the widgets in both frames in a file,but I am not able to figure out how do I refer to them and access their values.
Any help will be highly appreciated.Thanks in advance.
The widgets in which the user can write have a get method that returns their content. But in order to do this, you need to store your widget in a class variable for example.
Edit: I had misunderstood the problem and I hadn't realized that the add_widget function would be called for different containers for the same instance. One way to keep track of all created widgets is to create a widget list:
add self.widgets = [] in __init__
define theadd_widget method like that:
def add_widget(self, container):
self.widgets.append(Entry(container, text="enter text here"))
self.widgets[-1].pack()
Then to get the text entered by the user in all widgets (inside the write function):
texts = []
for widget in self.widgets:
texts.append(widget.get())

Python, using tkinter how to customize where classes of ui components are displayed?

I am very new to python, and am currently trying to organize my tkinter app in a slightly different way. I'm trying to use classes to make the app more modular and be able to use methods in the class in multiple places in the app. Here is the updated code that I have:
from tkinter import *
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
self.QUIT.pack(side=LEFT)
self.hi_there.pack(side=RIGHT)
Frame.__init__(self, master)
self.pack()
self.createAnotherWidget()
self.title_label.pack(side=LEFT)
self.title_entry.pack(side=RIGHT)
def say_hi(self):
print("hi there, everyone!")
def createWidgets(self):
self.QUIT = Button(self)
self.QUIT["text"] = "QUIT"
self.QUIT["fg"] = "red"
self.QUIT["command"] = self.quit
self.hi_there = Button(self)
self.hi_there["text"] = "Hello",
self.hi_there["command"] = self.say_hi
def createAnotherWidget(self):
self.title_label = Label(self)
self.title_label["text"] = "Title: "
self.title_entry = Entry(self)
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
self.createAnotherWidget()
root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
This runs without errors, but nothing shows in the window. How can I customize where the code for these methods will be placed when rendered? For this example, I'm simply wanting the createAnotherWidget to display below the two buttons in createWidgets
One solution is to have the caller be responsible for calling pack or grid on the individual widgets. This requires that you save references to the widgets somehow, such as attributes of the object. You do this already for some widgets, but not for others. You need to be consistent.
Do this by moving the calls to pack() from the functions and into your __init__:
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.createWidgets()
self.createAnotherWidget()
self.QUIT.pack(...)
self.hi_there.pack(...)
self.title_label.pack(...)
self.title_entry.pack(...)
Of course, you'll need to modify createAnotherWidget to save references to the widgets.
The point being, creating widgets and laying out widgets on the screen are two separate problems that should be solved separately.
That being said, it's a bit unusual to have functions that create multiple widgets that are designed to be stitched together by some other function.
A more common pattern is for functions to create widgets that are related, and to manage the layout of the related widgets itself. That way the caller only has to worry about organizing the groups of widgets rather than a bunch of individual widgets.
For example, you might have one function that creates a toolbar. Another that creates the main area with scrollbars. Another function would create a footer. Another that creates a form with a bunch of label and entry widgets. Another one that creates a label/entry combination. And so on.

PyQt Subclass from QTableWidgetItem and QWidget

Im making a QTableWidget in Pyqt and ran into a bit of an annoying hiccup.
I need to use widgets in my table for its functionality, so im using setCellWidget to add them to the table. However, widgets dont have the same methods available as QTableWidgetItem's do (especially regarding selection in the table).
Im wondering if its possible to do something subclassing both items, so i can have the methods of both, and how i woulda dd that to the table.
Something like:
class TableItem(QtGui.QTableWidgetItem, QtGui.QWidget):
def __init__(self, parent=None):
super(TableItem, self).__init__(parent)
self.check = QtGui.QCheckBox()
self.label = QtGui.QLabel('Some Text')
self.h_box = QtGui.QHBoxLayout()
self.h_box.addWidget(self.check)
self.h_box.addWidget(self.label)
and then somehow add that to my table as a TableWidgetItem so it displays widgets and also has selection methods available.
Any ideas here?
For reference:
setCellWidget: http://pyqt.sourceforge.net/Docs/PyQt4/qtablewidget.html#setCellWidget
QWidget: (easy to find, i cant post more than 2 links)
-Which doesnt have the nice methods for a table
QTableWidgetItem: http://pyqt.sourceforge.net/Docs/PyQt4/qtablewidgetitem.html#type
with isSelected and setSelected (Methods not avialble from a widget used in setCellWidget.
To return the widget in a cell you can use table.cellWidget(row, column) and then use your widgets methods on that. But beacuse setSelected and isSelected arent methods of a widget, you cant check for selection. I was hoping to subclass the two together to allow for both
--Basically I need to know how to get my class to 'return' the proper type when i call it to add to the table with setItem
I am not sure what you want to do but you could "inject" a method like:
class TableWidgetItem(QtGui.QTableWidgetItem):
def __init__(self, parent=None):
QtGui.QTableWidgetItem.__init__(self)
def doSomething(self):
print "doing something in TableWidgetItem"
class Widget(QtGui.QWidget):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self)
tableWidgetItem = TableWidgetItem()
widget = Widget()
def widgetFunction(self):
tableWidgetItem.doSomething()
# as an instance method
settatr(widget, "widgetFunction", MethodType(widgetFunction, widget, type(widget)))
# or as a class method
settatr(widget, "widgetFunction", widgetFunction)
Then you can:
>>>widget.widgetFunction()
doing something in TableWidgetItem
(not tested)

Categories

Resources