Add Scrollbar to popup table in Tkinter - user-interface

I have a menu button in a GUI I am making that displays a popup containing a CSV file, using pd.read_csv through pandas. However, there is a lot of data, and when the popup is displayed, pandas cuts off a lot of the data, only displaying the data in the beginning and in the end of the file.
I want to be able to scroll through all the data in my popup window. Any suggestions?
Here is the code for the popup command:
def popuptable():
popup = tk.Tk()
popup.wm_title("!")
label = ttk.Label(popup, text=(pd.read_csv('NameofCSVFile.csv')), font=NORM_FONT)
label.pack(side="top", fill="x", pady=10)
popup.mainloop()

I give you an example of how to do a scrollable text widget that looks like a label. I put it in the main window for this example, but you just have to replace root by a toplevel to adapt it to your case.
from tkinter import Tk, Text, Scrollbar
root = Tk()
# only the column containing the text is resized when the window size changes:
root.columnconfigure(0, weight=1)
# resize row 0 height when the window is resized
root.rowconfigure(0, weight=1)
txt = Text(root)
txt.grid(row=0, column=0, sticky="eswn")
scroll_y = Scrollbar(root, orient="vertical", command=txt.yview)
scroll_y.grid(row=0, column=1, sticky="ns")
# bind txt to scrollbar
txt.configure(yscrollcommand=scroll_y.set)
very_long_list = "\n".join([str(i) for i in range(100)])
txt.insert("1.0", very_long_list)
# make the text look like a label
txt.configure(state="disabled", relief="flat", bg=root.cget("bg"))
root.mainloop()
Screenshot:

Related

Placing multiple buttons in same column - Tkinter using grid

I am trying to create a GUI for displaying data in a way that the user can flip through pages using the page buttons on the bottom (page 1, 2, 3, etc.) The problem is currently the entire window I made has two columns of equal width. If I add buttons that say "1" "2" "3" "4" they get spread out in the two columns. I tried the sticky option but that still doesn't look right. I want the four buttons placed right next to each other in the middle of the bottom of my window. Is there some way I can do this without having to change the number of columns above?
I tried creating a frame and trying to see if I could fit more columns in that frame, but it ends up just adding those columns to the right of the other two columns.
fr=tk.Frame(master).grid(row=23,column=0, rowspan=1, columnspan=4)
b=tk.Button(fr,text='1',command=page1)
b.grid(row=23, column=1, sticky=tk.W)
b1=tk.Button(fr,text='2', command=page2)
b1.grid(row=23, column=1, sticky=tk.E)
b2=tk.Button(fr,text='3', command=page3)
b2.grid(row=23, column=2, sticky=tk.W)
b3=tk.Button(fr,text='4', command=page4)
b3.grid(row=23, column=2, sticky=tk.E)
You can simply create a new frame and give it your main frame as parent, then inside of it you can create how many columns you want and play around with it.
Here is a simple example:
app = tk.Tk()
fr=tk.Frame(app)
fr.grid(rowspan=2, columnspan=2)
# this represents what you have in the page above
something_large = tk.Button(fr, text="HELLO WORLD")
something_large_too = tk.Button(fr, text="Hello world")
something_large.grid(row=0, column=0)
something_large_too.grid(row=0, column=1)
bottom_frame = tk.Frame(fr)
bottom_frame.grid(row=1, columnspan=2)
b=tk.Button(bottom_frame,text='1')
b.grid(row=0, column=0)
b1=tk.Button(bottom_frame,text='2')
b1.grid(row=0, column=1,)
b2=tk.Button(bottom_frame,text='3')
b2.grid(row=0, column=2)
b3=tk.Button(bottom_frame,text='4')
b3.grid(row=0, column=3)
app.mainloop()
If you want the buttons to have some space between them just change their padx property when you grid them.

QComboBox popup animation glitch

When using a QComboBox in PySide2 the popup menu seems to initially start about 10 pixels or so to the left until its finished animating down at which point it pops (about) 10 pixels to the right into the correct position.
How can I fix this? Or am I able to disable the animation so the menu just opens without animating? And am I able to control the animation time for the popup?
Here are two screenshots, the top one is while the combobox dropdown is animating down and the bottom one is after the dropdown is open:
Here's the simple example code use to produce the combobox above:
from PySide2 import QtCore, QtWidgets
import sys
class MyDialog(QtWidgets.QDialog):
def __init__(self, parent=None):
super(MyDialog, self).__init__(parent)
self.setWindowTitle('Modal Dialogs')
self.setMinimumSize(300,80)
# remove help icon (question mark) from window
self.setWindowFlags(self.windowFlags() ^ QtCore.Qt.WindowContextHelpButtonHint)
# create widgets, layouts and connections (signals and slots)
self.create_widgets()
self.create_layouts()
self.create_connections()
def create_widgets(self):
self.combo = QtWidgets.QComboBox()
self.combo.addItems(['one','two','three'])
def create_layouts(self):
# self must be passed to the main_layout so it is parented to the dialog instance
main_layout = QtWidgets.QVBoxLayout(self)
main_layout.addWidget(self.combo)
def create_connections(self):
pass
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
my_dialog = MyDialog()
my_dialog.show() # Show the UI
sys.exit(app.exec_())

PyQt QToolBar with scrollbar

I need to create a toolbar (on the left side for example) that will contain many buttons. On default if overall height of all buttons is greater than the hight of toolbar these surplus buttons will be hidden. And I want to make this toolbar show all buttons and allow me to scroll down to see the rest. I couldn't find anything usefull on the web so far. Any ideas?
You should be able to stick the QToolBar inside a QScrollArea.
toolbar = QtGui.QToolBar()
toolbar.setOrientation(QtCore.Qt.Vertical)
for i in range(20):
toolbar.addAction('Action{0}'.format(i))
scroll_area = QtGui.QScrollArea()
scroll_area.setWidget(toolbar)
For anyone interested here is the solution:
Thanks to #Brendan Abel's answer I've came up with an idea. What I did is I've created my toolbar the same way I did before. Then I've added all my widgets (that previously were in this toolbar) to the new QWidget with QVBoxLayout. Then I've created a QScrollArea and set my recently-created-widget as a child widget of this scroll area. And finally I've added my ScrollArea to the Toolbar using addWidget().
class LeftToolbar(QtGui.QToolBar):
def __init__(self, *args):
QToolBar.__init__(self, *args)
self.setFloatable(False)
self.setMovable(False)
self.scroll_widget = QtGui.QWidget(self)
self.scroll_layout = QtGui.QVBoxLayout()
self.scroll_widget.setLayout(self.scroll_layout)
# Add your toolbar widgets here
self.ExampleWidget1 = QtGui.QLabel(self)
self.ExampleWidget1.setText("Example Text1")
self.scroll_layout.addWidget(self.ExampleWidget1)
self.ExampleWidget2 = QtGui.QLabel(self)
self.ExampleWidget2.setText("Example Text2")
self.scroll_layout.addWidget(self.ExampleWidget2)
# Create QScrollArea
self.scroll_area = QtGui.QScrollArea()
self.scroll_area.setWidget(self.scroll_widget)
self.addWidget(self.scroll_area)
# Create object LeftToolbar in your main window
self.LeftToolbar = LeftToolbar()
self.addToolBar(Qt.LeftToolBarArea, self.LeftToolbar)

How can I align items in menu bar from right to left with using python 3 and tkinter module?

I'm using python 3 and tkinter module for creating a GUI. I need to create a menu bar and align items on it from right to left (I want to use that with Persian language so I need to align my menu items from right to left), now I have used from this code but it didn't aligned file and edit items from right to left and they still align from left to right in the menubar. How can I deal with it?
from tkinter import *
from tkinter import ttk
root = Tk()
root.title('Create Menu bar and items')
root.geometry('300x300+100+50')
root.option_add('*tearOff', False)
menubar = Menu(root)
root.config(menu = menubar)
file = Menu(menubar)
edit = Menu(menubar)
menubar.add_cascade(menu = file, label = 'فایل',compound = RIGHT)
menubar.add_cascade(menu = edit, label = 'ویرایش',compound = RIGHT)
Use a simple trick, create a blank menu between the itens ;-)
blankmenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="".ljust(130), menu=blankmenu)
I don't believe you can do what you want. I've not used Tkinter with a right-to-left language so I can't say for sure, but you're limited to what the OS supports for menubars. Tkinter gives you no control over where items are placed on a menubar, other than the relative order.

Python 3.1 Tkinter layout help. I am close, please help me finish this

I am using Python 3.1 by the way.
I am trying to build a simple GUI using Tkinter - label, text entry field, button on the first row and editable text area with scrollbar to the right and on the bottom of it - on the second row. Please help me fix up the layout. What I have below does not quite work. If I have to use a grid, I will. I wish to keep the code very simple - I want to "sell" Python to some of my coworkers. So, I want to get a somewhat decent look and feel. Suggest better padding if you do not mind. Also, if my variable names, etc. seem weird, then please make a note.
At the same time I want to pretend that this is a throw-away script which I have not spent much time on. Since I am asking for your help, it ain't so, but they do not need to know ;). So, I do not want to introduce fancy code to create nice borders, etc. I just want something that is visually appealing, clean and simple. If I do not, then my presentation will not achieve its goal.
Thank you, my code is below:
class App:
def __init__(self, parent):
frame = Frame(parent)
self.__setup_gui(frame) # Call Helper
frame.pack(padx=15, pady=15)
parent.title('To be changed')
def __setup_gui(self, frame):
# First Row
self.cs_label = Label(frame, text='Change Set: ')
self.cs_label.pack(side=LEFT, padx=10, pady=10)
self.cs_val = Entry(frame, width=10)
self.cs_val.pack(side=LEFT, padx=10, pady=10)
self.get_button = Button(frame, text='Get', command=self.get_content)
self.get_button.pack(side=LEFT, padx=10, pady=10)
# Text area and scrollbar
self.text_area = Text(frame, height=10, width=50, background='white')
# Put a scroll bar in the frame
scroll = Scrollbar(frame)
self.text_area.configure(yscrollcommand=scroll.set)
self.text_area.pack(side=TOP)
scroll.pack(side=RIGHT,fill=Y)
self.clipboard_var = IntVar()
self.notepad_var = IntVar()
def get_content(self):
print(self.clipboard_var.get())
print(self.notepad_var.get())
###################################################################################################
if __name__ == '__main__':
root = Tk()
app = App(root)
root.mainloop()
You definitely want the grid manager -- Pack only works for a vertical or horizontal stackup by itself. You can use multiple frames to work around it, but I find it's easier to expand a GUI if you just do it with Grid to start.
Here's what I've worked up real quick based what you said and the code. I reduced/removed the padding -- it looked huge for me -- and I set up two scrollbars, in a subframe to make the padding work out more easily. Note that to make the horizontal scrollbar useful your Text area needs to have wrap=NONE; otherwise you might as well use the easy 'ScrolledText' widget from tkinter.scrolledtext and skip the horizontal scroll bar.
I've now reframed things a bit to allow for resize, with a minimum size that shows the top buttons -- see the uses of minsize and row/columnconfigure.
BTW, it looks like your variables aren't being pulled from anywhere -- is that intentional?
from tkinter import *
class App:
def __init__(self, parent):
self.__setup_gui(parent) # Call Helper
parent.title('To be changed')
def __setup_gui(self, parent):
# First Row
self.rowframe = Frame(parent)
self.rowframe.grid()
self.cs_label = Label(self.rowframe, text='Change Set: ')
self.cs_label.grid(row=0, column=0, padx=2, pady=2)
self.cs_val = Entry(self.rowframe, width=10)
self.cs_val.grid(row=0, column=1, padx=2, pady=2)
self.get_button = Button(self.rowframe, text='Get', command=self.get_content)
self.get_button.grid(row=0, column=2, padx=2, pady=2)
parent.update_idletasks()
parent.minsize(width=self.rowframe.winfo_width(), height=self.rowframe.winfo_height())
# Text area and scrollbars
self.textframe = Frame(parent)
self.textframe.grid(row=1, columnspan=2, padx=2, pady=2, sticky=N+S+E+W)
self.hscroll = Scrollbar(self.textframe, orient=HORIZONTAL)
self.vscroll = Scrollbar(self.textframe)
self.text_area = Text(self.textframe, height=10, width=50, wrap=NONE, background='white', yscrollcommand=self.vscroll.set, xscrollcommand=self.hscroll.set)
self.text_area.grid(row=0, column=0, sticky=N+S+E+W)
self.hscroll.config(command=self.text_area.xview)
self.hscroll.grid(row=1, column=0, sticky=E+W)
self.vscroll.config(command=self.text_area.yview)
self.vscroll.grid(row=0, column=1, sticky=N+S)
# Row 0 defaults to 0
parent.rowconfigure(1, weight=1)
parent.columnconfigure(1, weight=1)
# Textarea setup
self.textframe.rowconfigure(0, weight=1)
self.textframe.columnconfigure(0, weight=1)
self.clipboard_var = IntVar()
self.notepad_var = IntVar()
def get_content(self):
print(self.clipboard_var.get())
print(self.notepad_var.get())
###################################################################################################
if __name__ == '__main__':
root = Tk()
app = App(root)
root.mainloop()
Now, all that said...you might get more visual appeal with PyGTK, PyQt, or wxPython, though tkinter coming "standard" is a nice feature.

Resources