I want to show the text from the 'Yes' and the 'No' button in the informative text of a QMessageBox, but I don't see how I can get these labels from the buttons.
from PyQt5.QtWidgets import *
import sys
app = QApplication(sys.argv)
msgbox = QMessageBox()
msgbox.setStandardButtons(msgbox.Yes | msgbox.No)
info_text = "Click '{yes}' to confirm. Click '{no}' to abort."
msgbox.setInformativeText(info_text)
if msgbox.exec_() == msgbox.Yes:
print("Confirmed")
else:
print("Aborted")
By calling setStandardButtons, the button order and the button labels will be set to the default for the current operating system and the current language setting. How can I obtain these defaults so that I can use them for the slots in the string info_text?
I thought about using the buttons attribute from the QMessageBox object, which is a list of QPushButton objects. I can read the labels from there, but I don't see how I could determine whether the first element in the list is the Yes or the No button.
Okay, I was being stupid: along side the buttons attribute, there is also the button() method, which takes as its argument the button type that I want to retrieve. I can then use text() to get the label. Finally, the hotkey marker & has to be stripped from the label:
info_text = "Click '{yes}' to confirm. Click '{no}' to abort.".format(
yes=msgbox.button(msgbox.Yes).text().replace("&", ""),
no=msgbox.button(msgbox.No).text().replace("&", ""))
msgbox.setInformativeText(info_text)
Related
The following code creates a standard listbox in tkinter. In normal use, after the user makes the first listbox selection with a mouse click, subsequent selections can be made either by clicking again with the mouse, or by using the up/down cursor keys. Both of these (mouse click and cursor keys) correctly trigger ListboxSelect and change the value of SelectedIndex using the associated function UserClickedSelection(event).
The code also includes a function that allows me to set a listbox selection programmatically. This works perfectly, and correctly changes SelectedIndex using the SetSelection(index) function. But...and this is the problem...after making a selection programmatically, the up/down arrow keys no longer function. The user needs to make the next selection using the mouse, and then the up/down arrow keys once again function normally.
import tkinter as tk
root = tk.Tk()
root.geometry("300x300")
SelectedIndex = 0
def UserClickedSelection(event): # get user selection
global SelectedIndex
SelectedIndex = mylistbox.curselection()[0]
def SetSelection(index): # set selection
global SelectedIndex
mylistbox.selection_clear(0,tk.END)
mylistbox.selection_set(index)
mylistbox.activate(index)
SelectedIndex = mylistbox.curselection()[0]
mylistbox = tk.Listbox(root,activestyle="none")
mylistbox.place(x=0,y=0)
mylistbox.config(selectmode=tk.BROWSE)
mylistbox.config(exportselection=False)
mylistbox.bind('<<ListboxSelect>>',UserClickedSelection)
mylist = ['Zero','One','Two','Three','Four','Five']
mylistbox.insert(0,*mylist)
# Using function: set selection to index 2
SetSelection(2)
root.mainloop()
As you can see, in the code I've used the programmatic function to select index 2 of the listbox. This works fine, but the up/down arrow keys do not work until another selection is made afterwards using a mouse click. So there is clearly a difference between a "real" user selection and my "programmatic" selection. Is there some way to rectify this? I need the up/down arrow keys to work consistently. Thanks in advance for any assistance.
If I understand the problem correctly, you just need to make sure the listbox has focus.
def SetSelection(index): # set selection
...
mylistbox.focus_set()
I am creating a post form that will send my input as dictionary to a server. I planned to display the user entered input in a TextArea with my first display button click. This display button sets the next button (Send) to be visible. The Send button then convert or saves the values to a dictionary (key/value pair).
In my code, i followed the example in the ipywidget documentation (https://ipywidgets.readthedocs.io/en/latest/examples/Widget%20Styling.html [cell 12]) by adding all my widgets in a list. I am have difficulty in calling the values of the widget items to display in the Text area
I have tried to access the values using children[0].values but get error each time. AttributeError: 'Button' object has no attribute 'values'. I will appreciate anyone's help to do this form. If i can get my inputs as a dictionary, that will be very helpful
from ipywidgets import Layout, Button, Box, FloatText, Textarea, Dropdown, Label, IntSlider, Text
#Form item layout
form_item_layout = Layout(
display='flex',
flex_flow='row',
justify_content='space-between'
)
#form container
form_items = [
Box([
Label(value='Name'),
Text(value='John')
], layout=form_item_layout),
Box([
Label(value='Collection UUID'),
Dropdown(options=['theme', 'play', 'character'])
], layout=form_item_layout),
Box([Label(value='Result'),
Textarea(rows = 20)], layout=form_item_layout),
Button(description="display"),
Button(description="Send", button_style='success')
]
#box layout that holds the forms
box_lyt = Layout(
display='flex',
flex_flow='column',
border='solid 2px',
align_items='stretch',
width='50%'
)
form = Box(children=form_items, layout=box_lyt)
display(form)
form.children[4].layout.visibility = 'hidden'
def show(b):
form.children[4].layout.visibility = 'visible'
form.children[2] = c.children[0] + c.children[1] + c.children[2]
#Convert textarea values to dictionary
def list_children(c):
return c.children[2].to_dict()
form.children[3].on_click(show)
form.children[4].on_click(list_children )
I expect a widget displaying: Name, ID, result and display button. Clicking the display should show the values in the result TextArea and make the button (send) visible. Clicking the Send button should accept these values from result and save as dictionary. The widget displays but is not responsiveenter image description here
I have an issue with curselection of ListBox. It appears in Python 3.6. In Python 3.4 everything works fine. My code selects items from ListBox and put it in Entry widget. It works perfectly well when i click on the items in ListBox. But sometimes (after 5-10 clicks) when I click in Entry widget an error appears:
_tkinter.TclError: bad listbox index "": must be active, anchor, end, #x,y, or a number
Here's my code sample:
from tkinter import *
def insert_into_entry(event):
index=list_box.curselection()
print(index)
selected_item=list_box.get(index)
entry1.delete(0,END)
entry1.insert(END,selected_item)
window=Tk()
entry=Entry(window)
entry.grid(row=0,column=0)
list_box=Listbox(window,height=5,width=45)
list_box.grid(row=1,column=0)
list_box.bind('<<ListboxSelect>>',insert_into_entry)
entry1=Entry(window)
entry1.grid(row=2,column=0)
a=['one','two','three','four']
for i in a:
list_box.insert(END,i)
window.mainloop()
I tried to examine changes in index value. And error brings about when after clicking in Entry widget index returns empty tuple. It's my first question so I'll be greatfull for every response.
From what I can see by testing <<ListboxSelect>> I believe that the <<ListboxSelect>> event activates every time the selection changes even if that selection changes to "nothing selected". I believe this is why when you click off of the listbox and into any other field and the <<ListboxSelect>> event is triggered your insert_into_entry function is getting an empty tuple from curselection().
According to the documentation here the courselection() method will return an empty tuple if nothing is selected.
To avoid any errors we can first check if the results of ndex = list_box.curselection() are not equal to () an empty tuple. If not then perform the rest of the function. This should prevent any errors caused by this behaviour with the <<ListboxSelect>> event being called outside of the listbox.
Oh and one other thing. Don't use built in names for variable names. change index = list_box.curselection() to something like ndex = list_box.curselection()
from tkinter import *
window=Tk()
def insert_into_entry(Event = None):
ndex = list_box.curselection()
if ndex != ():
selected_item=list_box.get(ndex)
entry1.delete(0,END)
entry1.insert(END,selected_item)
entry=Entry(window)
entry.grid(row=0,column=0)
list_box=Listbox(window,height=5,width=45)
list_box.grid(row=1,column=0)
list_box.bind('<<ListboxSelect>>', insert_into_entry)
entry1=Entry(window)
entry1.grid(row=2,column=0)
a=['one','two','three','four']
for i in a:
list_box.insert(END,i)
window.mainloop()
We're building a GUI interface with Python+tkinter.
The problem is when we want to set the view mode of an entity. I need to set the view mode or state of the treeview widget as 'disabled'.
How can we solve it?
Thanks for any support.
UPDATE
self.frmTab01.trvDetailorder.configure(selectmode='none')
I'm looking for a solution in which appart from disable the selection, affect the visualization of the widget just like an entry widget.
nbro is right, you need to change the Treeview style to make it look disabled. In addition, I also deactivated the possibility to open/close items when the Treeview is disabled using binding tricks on the mouse click.
In my example I added an entry so that you can compare the look on the two widgets. If you are using OS X or Windows, you might need to change the theme (style.theme_use("clam") should do) because their default themes are not very customizable.
from tkinter import Tk
from tkinter.ttk import Treeview, Style, Button, Entry
root = Tk()
def toggle_state():
if "disabled" in tree.state():
e.state(("!disabled",))
tree.state(("!disabled",))
# re-enable item opening on click
tree.unbind('<Button-1>')
else:
e.state(("disabled",))
tree.state(("disabled",))
# disable item opening on click
tree.bind('<Button-1>', lambda e: 'break')
style = Style(root)
# get disabled entry colors
disabled_bg = style.lookup("TEntry", "fieldbackground", ("disabled",))
disabled_fg = style.lookup("TEntry", "foreground", ("disabled",))
style.map("Treeview",
fieldbackground=[("disabled", disabled_bg)],
foreground=[("disabled", "gray")],
background=[("disabled", disabled_bg)])
e = Entry()
e.insert(0, "text")
e.pack()
tree = Treeview(root, selectmode='none')
tree.pack()
tree.insert("", 0, iid="1", text='1')
tree.insert("1", 0, iid='11', text='11')
Button(root, text="toggle", command=toggle_state).pack()
root.mainloop()
I'm working on an application in PyQt that takes an object dictionary and allows you to plot the variables streaming from a robot in real time. One of the things I'm working on to enable this is a drop down menu. Unfortunately, we have a couple hundred variables, so my PyQt Combobox pops up from the top of the screen to the bottom with items when clicked. I'd like to limit the number of items displayed at a time to 20, with the ability to scroll to see the rest. I've tried using the documented setMaxVisibleItems method, but it doesn't affect the drop down at all. Any recommendations?
Code here:
#!/usr/bin/env python
from PyQt4.QtCore import Qt
from PyQt4.QtGui import QComboBox, QApplication
from cli.parc2_od import cli_od
import sys
app = QApplication(sys.argv)
items = cli_od.OD.keys() #Items to populate dropdown.
combo = QComboBox()
#The solution:
combo.setStyleSheet("QComboBox { combobox-popup: 0; }")
combo.setMaxVisibleItems(10)
combo.addItems(items)
combo.resize(300, 30)
combo.show()
sys.exit(app.exec_())
According to the documentation:
The property maxVisibleItems is ignored for non-editable comboboxes in styles that returns true for `QStyle::SH_ComboBox_Popup such as the Mac style or the Gtk+ Style.
And you can override that SH_ComboBox_Popup style hint with a style sheet:
combo.setStyleSheet("QComboBox { combobox-popup: 0; }");