how to display a form within a frame using python and tkinter - python-2.7

I have created a notebook(file1.py) using python and tkinter. This notebook has three tabs A,B,C. I have another python file(file2.py) which contains few text fields. Now I am looking for a way to display the contents of the other file2.py within the tab A which is in file1.py.The following is the code I used in file1.py
import tkinter as tk
import tkinter.ttk as ttk
root = tk.Tk()
# use width x height + x_offset + y_offset (no spaces!)
root.geometry("%dx%d+%d+%d" % (300, 200, 100, 50))
root.title('test the ttk.Notebook')
nb = ttk.Notebook(root)
nb.pack(fill='both', expand='yes')
# create a child frame for each page
f1 = tk.Frame(bg='red')
f2 = tk.Frame(bg='blue')
f3 = tk.Frame(bg='green')
# create the pages
nb.add(f1, text='A')
nb.add(f2, text='B')
nb.add(f3, text='C')
# put a button widget on child frame f1 on page1
btn1 = tk.Button(f1, text='button1')
btn1.pack(side='left', anchor='nw', padx=3, pady=5)
root.mainloop()
File2.py
import sys
from PyQt4 import Qt
from taurus.qt.qtgui.application import TaurusApplication
app = TaurusApplication(sys.argv)
panel = Qt.QWidget()
layout = Qt.QHBoxLayout()
panel.setLayout(layout)
from taurus.qt.qtgui.panel import TaurusForm
panel = TaurusForm()
model = [ 'test/i1/1/%s' % p for p in props ]
panel.setModel(model)
panel.show()
sys.exit(app.exec_())
I am new to using tkinter and python so could you let me know how I could achieve it. Also in the other file(file2.py) I have few import statements like 'import sys" etc.Thanks.

You cannot mix those two files. One uses Tkinter, one uses PyQT. Those two libraries are incompatible with each other.

Related

Python executable hangs with plt.show()

I am creating a GUI application (EXE) in Python 2.7 on Win 10 platform.
The application is supposed to plot a graph (using matplotlib) with user provided parameters. When the user changes the values and presses the plot button again, new graph should be plotted on the same figure retaining the previous curves for ease of comparison (also a requirement).
I had to use plt.show() at the end of the script to show the graph when running the exe file of my program.
Problem: Application freezes and crashes when the plot button is pressed the second time. For the first time, everything goes fine and the graph is displayed.
Solutions tried:
Going thru so many threads, I tried following solutions without luck:
Used plt.draw() instead of plt.show() because the later blocks program execution. But draw() does not display the graphs.
Tried plt.pause(), the application gives RunTime error and crashes.
Also played with ion() / ioff().
Tried plt.show(block = False), the application crashes on second click on plot button.
I came across various backends that can be used with matplotlib and suspected that plt.show() might work well with other backends. Tried TkAgg, WxAgg, and others but no luck.
I would really appreciate if someone can help me with this...already tried for 3 days!!
Code sample:
from PyQt4 import QtCore, QtGui
import numpy as np
import matplotlib
matplotlib.use('TkAgg') #Trying different backends
import matplotlib.pyplot as plt
plt.rc('xtick', labelsize = 16)
plt.rc('ytick', labelsize = 16)
import FileDialog #These three imports needed for EXE
import tkFileDialog
import tkMessageBox
class Ui_MainWindow(object):
def setupUi(self, MainWindow):
#UI elements code...
def retranslateUi(self, MainWindow):
#Other code lines
def my_Plot_Function():
#Some calculations
plt.figure('My title')
plt.plot(x, y, label = 'My Label')
plt.grid(True)
plt.axhline(y = 0, color = 'k')
plt.xlabel(' X ', fontsize = 16)
plt.ylabel(' Y ', fontsize = 16)
plt.legend(prop={'size': 14})
plt.show()
if __name__ == "__main__":
import sys
app = QtGui.QApplication(sys.argv)
MainWindow = QtGui.QMainWindow()
ui = Ui_MainWindow()
ui.setupUi(MainWindow)
MainWindow.show()
sys.exit(app.exec_())

Adding notebook tabs in tkinter - how do I do it with a class-based structure? (Python 2)

I want each tab to come from it's own class (classes are in their own files - I am just testing the first one for now).
Here is what I tried:
tab1.py
from Tkinter import *
import Tkinter as tk
class Tab(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master)
fr = Frame(self).pack()
Label(fr, text="one", bg='red', bd=2).pack()
Label(fr, text="two", bg='yellow', bd=2).pack()
if __name__ == '__main__':
root = Tk()
frame = Frame(root).pack()
Tab(frame)
Button(frame, text='only if class', command=root.destroy).pack()
mainloop()
noteBook.py
from Tkinter import *
from ttk import *
from tab1 import Tab
root = Tk()
note = Notebook(root)
main_frame = Frame(note)
button1 = Button(main_frame, text='test').pack()
#tab1 = Tab(note)
tab1 = Frame(note)
tab2 = Frame(note)
tab3 = Frame(note)
Tab(tab1)
Button(tab1, text='Exit', command=root.destroy).pack()
note.add(tab1, text = "Tab One", compound=TOP)
note.add(tab2, text = "Tab Two")
note.add(tab3, text = "Tab Three")
note.pack()
root.mainloop()
exit()
run with:
python2.7 noteBook.py
The problem is that the content of tab1.py does not appear within the first tab, it instead appears within the frame that contains the whole noteBook.
Also when running tab1.py directly with python2.7 noteBook.py I need it to behave properly meaning from what it has now it should show just the tab with an extra button from the if __name___... part.
I have come accros multiple examples but only found one that was what I want but it had no working solution and it was for python3 - I would like python2. python3 question with no working answer Thanks.
The problem is this line of code:
fr = Frame(self).pack()
When you do the above, fr is None because .pack() returns None (because x().y() returns the value of y()). Later, you do this:
Label(fr, text="one", bg='red', bd=2).pack()
Since fr is None, the label is created in the root window.
Unrelated to the problem, here's some advice: you are creating too many frames. You don't need fr inside of Tab, and you don't need tab1, tab2, or tab3
Here's all you need for Tab:
class Tab(tk.Frame):
def __init__(self, master):
tk.Frame.__init__(self, master, background="pink")
Label(self, text="one", bg='red', bd=2).pack()
Label(self, text="two", bg='yellow', bd=2).pack()
To add it to the notebook, you just need two lines:
tab1 = Tab(note)
note.add(tab1, text = "Tab One", compound=TOP)
This works perfectly and just for fun I've illustrated the populating of tabs 2 and 3 althought I just reused the same class for simplicity here. The goal was to be able to run the tabs directly to view them alone during developpement without having to run the whole thing every time.
noteBook.py
from Tkinter import *
from ttk import *
from tab1 import Tab
root = Tk()
note = Notebook(root)
main_frame = Frame(note)
button1 = Button(main_frame, text='test').pack()
tab1 = Frame(note)
tab2 = Frame(note)
tab3 = Frame(note)
Tab(tab1)
Tab(tab2)
Tab(tab3)
Button(tab1, text='Exit', command=root.destroy).pack()
note.add(tab1, text = "Tab One", compound=TOP)
note.add(tab2, text = "Tab Two")
note.add(tab3, text = "Tab Three")
note.pack()
root.mainloop()
exit()
tab1.py
import Tkinter as tk
class Tab(tk.Frame):
def __init__(self, parent_widget):
tk.Frame.__init__(self, parent_widget)
self.fr = tk.Frame(parent_widget, width=200, height=200, bg='pink', bd=2)
tk.Label(self.fr, text="one", bg='red', bd=2).pack()
tk.Label(self.fr, text="two", bg='yellow', bd=2).pack()
self.fr.pack() # this packing must be done after 2 above packings
if __name__ == '__main__':
root = tk.Tk() # the app window
main_frame = tk.Frame(root, height=200, width=200, bg='blue', bd=2) # main frame
Tab(main_frame) # instatiate Tab(), sending main_frame as the parent_widget
tk.Button(main_frame, text='only if class', command=root.destroy).pack()
main_frame.pack() # display main frame on window
tk.mainloop()

Python Tkinter: destroy() my Toplevel() window

I don't understand what I'm doing wrong.
I'm trying to create a log in window. When you click Log in, I want to to go do stuff and after that close out and go to the main GUI.
I found a bunch of stuff online that I can't make heads or tails of. I do not want to cut and paste other people's code which I do not fully understand.
So I'd like to understand what I'm doing wrong here. To start I created a destroyWindow() method which I call from the button as just a starting point.
There is a scope issue where loginWindow does not exist within its own class. I thought the class application would get around the scope issue. I tried using 'self.' but to no avail. I tried random things I saw in other people's code. Please can someone pinpoint what I'm missing here? I get
NameError: global name 'loginWindow' is not defined
#!/Usr/bin/Python
import Tkinter,tkFileDialog,tkMessageBox
from Tkinter import *
from tkFileDialog import *
import sys, time, datetime
import pathlib
from pathlib import * #makes it really easy to travers folders if needed.
mainWindow = Tk()
mainWindow.wm_title("my prog")
mainWindow.wm_iconbitmap('fb_logo_sm.ico')
mainFrame = Frame(mainWindow)
mainFrame.grid(padx=10,pady=10)
class loginWindowClass():
def __init__(self):
loginWindow = Tkinter.Toplevel()
loginWindow.configure(bg='#22BEF2')
loginWindowFrame = Frame(loginWindow,bg='#22BEF2')
loginWindowFrame.grid(padx=90,pady=50)
loginWindow.wm_title("log in")
loginWindow.wm_iconbitmap('my.ico')
usernameLable = Tkinter.Label(loginWindowFrame,text="User Name",fg='#FFFFFF',bg='#22BEF2')
usernameLable.grid(row=1,column=2,padx=(0,5),sticky=W+S)
usernameField = Entry(loginWindowFrame)
usernameField.config(width=24)
usernameField.grid(row=2,column=2)
passwordLable =Tkinter.Label(loginWindowFrame,text="Password",fg='#FFFFFF',bg='#22BEF2')
passwordLable.grid(row=3,column=2,sticky=W+S)
passwordField = Entry(loginWindowFrame)
passwordField.config(width=24)
passwordField.grid(row=4,column=2)
loginButton = Button(loginWindowFrame, text='Log In', height=1, width=20, wraplength=100, fg='white',bg='#bbbbbb',command=self.destroyWindow).grid(row=5,column=2,pady=(10,0))
def destroyWindow(self):
loginWindow.destroy()
logwin = loginWindowClass()
mainWindow.mainloop()
Ah. 'self.' is the answer indeed.
I did not apply it everywhere. Here is the solution
#!/Usr/bin/Python
import Tkinter,tkFileDialog,tkMessageBox
from Tkinter import *
from tkFileDialog import *
import sys, time, datetime
import pathlib
from pathlib import * #makes it really easy to travers folders if needed.
mainWindow = Tk()
mainWindow.wm_title("my prog")
mainWindow.wm_iconbitmap('fb_logo_sm.ico')
mainFrame = Frame(mainWindow)
mainFrame.grid(padx=10,pady=10)
class loginWindowClass():
def __init__(self):
self.loginWindow = Tkinter.Toplevel()
self.loginWindow.configure(bg='#22BEF2')
loginWindowFrame = Frame(self.loginWindow,bg='#22BEF2')
loginWindowFrame.grid(padx=90,pady=50)
self.loginWindow.wm_title("log in")
self.loginWindow.wm_iconbitmap('my.ico')
usernameLable = Tkinter.Label(loginWindowFrame,text="User Name",fg='#FFFFFF',bg='#22BEF2')
usernameLable.grid(row=1,column=2,padx=(0,5),sticky=W+S)
usernameField = Entry(loginWindowFrame)
usernameField.config(width=24)
usernameField.grid(row=2,column=2)
passwordLable =Tkinter.Label(loginWindowFrame,text="Password",fg='#FFFFFF',bg='#22BEF2')
passwordLable.grid(row=3,column=2,sticky=W+S)
passwordField = Entry(loginWindowFrame)
passwordField.config(width=24)
passwordField.grid(row=4,column=2)
loginButton = Button(loginWindowFrame, text='Log In', height=1, width=20, wraplength=100, fg='white',bg='#bbbbbb',command=self.destroyWindow).grid(row=5,column=2,pady=(10,0))
def destroyWindow(self):
self.loginWindow.destroy()
logwin = loginWindowClass()
mainWindow.mainloop()

tkinter progressbar with text inside it

import Tkinter
import ttk
def main():
root = Tkinter.Tk()
root.geometry("500x200")
ft = ttk.Frame()
ft.pack(expand=True, fill=Tkinter.BOTH, side=Tkinter.TOP)
pb_hd = ttk.Progressbar(ft, orient='horizontal', mode='indeterminate')
pb_hd.pack(expand=False, fill=Tkinter.BOTH, side=Tkinter.TOP)
pb_hd.start(50)
root.mainloop()
if __name__ == '__main__':
main()
I want to add text inside the progress bar but not getting any idea how to do it?
The ttk progressbar does not support a text option. You can create a label and pack it immediately above or below the widget.

TreeView in a ScrollView in Kivy - No Scroll

I'm working on a kivy app that pulls data from an sqlite3 database and populates a TreeView with it. The TreeView becomes too large to fit on my screen when I expand a few of the groups so I want to put it inside a ScrollView so I can still scroll down and see the items that have gone off the bottom of my screen. I can get a basic ScrollView to work, but when I put my TreeView inside it there is no scrolling and the top part of my TreeView is off the top of my screen.
I have trimmed down the code into this working example of the problem that runs without a .kv file:
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.uix.treeview import TreeView, TreeViewNode
from kivy.uix.treeview import TreeViewLabel
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.button import Button
class TreeViewButton(Button, TreeViewNode):
pass
modGroups = [u'Fruit', u'Fruit', u'Meat', u'Dairy', u'Dairy', u'Fruit']
modItems = [u'Apple', u'Pear', u'Spam', u'Egg', u'Milk', u'Banana']
modDict = dict()
modDictUnique = dict()
def populate_tree_view(tv):
modDict = zip(modGroups, modItems)
print modGroups
print modItems
for k, v in modDict:
if k not in modDictUnique:
modDictUnique[k] = [v]
else:
modDictUnique[k].append(v)
sortedGroups = modDictUnique.keys()
sortedGroups.sort()
#print modItems
#print modDictUnique
n = tv.add_node(TreeViewLabel(text='Food', is_open=True))
for group in sortedGroups:
g = tv.add_node(TreeViewLabel(text='%s' % group), n)
for item in modDictUnique[group]:
tv.add_node(TreeViewButton(text='%s' % item), g)
class POSFMApp(App):
def build(self):
layout = GridLayout(cols=1, spacing=50, size_hint_y=None,width=800)
layout.bind(minimum_height=layout.setter('height'))
#for i in range(30):
# btn = Button(text=str(i), size=(480, 40),
# size_hint=(None, None))
# layout.add_widget(btn)
tv = TreeView(root_options=dict(text='Tree One'), hide_root=True, indent_level=4, minimum_height=5000)
populate_tree_view(tv)
layout.add_widget(tv)
root = ScrollView(size_hint=(None, None), size=(800, 700))
root.center = Window.center
root.add_widget(layout)
return root
if __name__ == '__main__':
POSFMApp().run()
In my actual app, modGroups and modItems are populated from an sqlite3 database, but this example presents the problem without having to mess around with sqlite3. I put in the (commented out) lines:
#for i in range(30):
# btn = Button(text=str(i), size=(480, 40),
# size_hint=(None, None))
# layout.add_widget(btn)
from this kivy ScrollView example to show that if I uncomment these lines and comment out the three lines about my TreeView
tv = TreeView(root_options=dict(text='Tree One'), hide_root=True, indent_level=4, minimum_height=5000)
populate_tree_view(tv)
layout.add_widget(tv)
Then I can get a working ScrollView with a scroll bar on the right as expected when I use my mouse's scroll wheel.
My best guess is that the TreeView doesn't tell the ScrollView how long it is vertically so the ScrollView doesn't realize it needs to scroll on the y-axis. That's just a guess, though.
How can I get a TreeView to work inside a ScrollView so I can scroll (especially on the y-axis) through my TreeView?
a) Using a GridLayout just for one child, pease don't. I'll asume that it's a left over from when/if you add more children to it.
b) Documentation of TreeView states that it has minimun_height property which indicates the minimum width/height needed to hold all it's children. The Treeview does not change it's height on it's own depending on the no of children. You should update (in this case) TreeViews height to it's minimum_height... tv.bind(minimum_height=tv.setter('height'))
c) taking into account the information provided in the points above, you can just do::
tv = TreeView(root_options=dict(text='Tree One'), hide_root=True, indent_level=4)
tv.size_hint = 1, None
tv.bind(minimum_height = tv.setter('height'))
populate_tree_view(tv)
root = ScrollView(pos = (0, 0))
root.add_widget(tv)
Here is the entire code including these changes so one can just copy and paste the code to a .py file and run it.
from kivy.uix.scrollview import ScrollView
from kivy.uix.gridlayout import GridLayout
from kivy.core.window import Window
from kivy.uix.widget import Widget
from kivy.uix.treeview import TreeView, TreeViewNode
from kivy.uix.treeview import TreeViewLabel
from kivy.app import App
from kivy.properties import ObjectProperty, StringProperty
from kivy.uix.button import Button
class TreeViewButton(Button, TreeViewNode):
pass
modGroups = [u'Fruit', u'Fruit', u'Meat', u'Dairy', u'Dairy', u'Fruit']
modItems = [u'Apple', u'Pear', u'Spam', u'Egg', u'Milk', u'Banana']
modDict = dict()
modDictUnique = dict()
def populate_tree_view(tv):
modDict = zip(modGroups, modItems)
print modGroups
print modItems
for k, v in modDict:
if k not in modDictUnique:
modDictUnique[k] = [v]
else:
modDictUnique[k].append(v)
sortedGroups = modDictUnique.keys()
sortedGroups.sort()
#print modItems
#print modDictUnique
n = tv.add_node(TreeViewLabel(text='Food', is_open=True))
for group in sortedGroups:
g = tv.add_node(TreeViewLabel(text='%s' % group), n)
for item in modDictUnique[group]:
tv.add_node(TreeViewButton(text='%s' % item), g)
class POSFMApp(App):
def build(self):
#for i in range(30):
# btn = Button(text=str(i), size=(480, 40),
# size_hint=(None, None))
# layout.add_widget(btn)
tv = TreeView(root_options=dict(text='Tree One'), hide_root=True, indent_level=4)
tv.size_hint = 1, None
tv.bind(minimum_height = tv.setter('height'))
populate_tree_view(tv)
root = ScrollView(pos = (0, 0))
root.add_widget(tv)
return root
if __name__ == '__main__':
POSFMApp().run()
Add hight to TreeView then it will scroll. Like this.
ScrollView:
id: kr_scroll
do_scroll_x: False
TreeView:
id: trvMenu
root_options: { 'text': 'Home', 'font_size': 15}
hide_root: False
indent_level: 4
size_hint_y: None
height: self.parent.height*2