hey folks using Python i have bind the radio button and when that's clicked the TextCtrl is called upon but after I type in TextCtrl i am not able to get the string that has been entered, My code goes like this
def A(self,event):
radiobut = wx.RadioButton(self.nameofframe, label = 'Opt-1', pos = (10,70),size= (90,-1))
self.Bind(wx.EVT_RADIOBUTTON,self.B,radiobut)
def B(self,event):
Str1 = wx.TextCtrl(self.nameofframe,pos = (100,70), size=(180,-1))
print Str1.GetValue()
Could anyone please tell me where is the problem . Why can't i get it printed ?
Str1.GetValue() will be empty because when the radio button is clicked you are creating a new TextCtrl and then immediatly getting its value, it will be empty as the user has not been able to type anything in it yet.
Radio button usually comes within a group, one or more more than one, and one at least should clicked but you have only one button. What is usually used in such case is a check box, CheckBox.
In this example, it prints the text entered in TextCtrl when a CheckBox is activated:
#!python
# -*- coding: utf-8 -*-
import wx
class MyFrame(wx.Frame):
def __init__(self, title):
super(MyFrame, self).__init__(None, title=title)
panel = wx.Panel(self)
self.check = wx.CheckBox(panel, label='confiurm?', pos =(10,70), size=(90,-1))
self.text = wx.TextCtrl(panel, pos=(100,70), size=(180,-1))
# disable the button until the user enters something
self.check.Disable()
self.Bind(wx.EVT_CHECKBOX, self.OnCheck, self.check)
self.Bind(wx.EVT_TEXT, self.OnTypeText, self.text)
self.Centre()
def OnTypeText(self, event):
'''
OnTypeText is called when the user types some string and
activate the check box if there is a string.
'''
if( len(self.text.GetValue()) > 0 ):
self.check.Enable()
else:
self.check.Disable()
def OnCheck(self, event):
'''
Print the user input if he clicks the checkbox.
'''
if( self.check.IsChecked() ):
print(self.text.GetValue())
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame('Example')
self.frame.Show()
return True
MyApp(False).MainLoop()
This is how it works:
Here is the usual way of doing it.
Create the text control when you create the frame. Save a pointer ( sorry C++ - whatever you do with python ) to the text control and bind a method to the EVT_TEXT_ENTER event. When the event fires, you can read what the user typed.
If you want to control when and when not the text control is visible, use the hide() method.
Related
I'm using a combo box as a simple command line with a history.
Here's the signal-slot definition:
QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return),
self.comboBox_cmd,
activated=self.queryLine)
...and the slot:
#QtCore.pyqtSlot()
def queryLine(self):
'''
Read cmd string from widget and write to device.
'''
## comboBox can be enhanced with a history
cmd = self.comboBox_cmd.currentText()
cmds = [self.comboBox_cmd.itemText(i) for i in range(self.comboBox_cmd.count())]
if not cmds or cmds[-1] != cmd:
self.comboBox_cmd.addItem(cmd)
self.query(cmd)
This works really well. Now, how can I mark the entire text of the current item after pressing Enter, so that I can replace the whole line if I so wish?
You can automatically select the text of the line edit by catching the return/enter key press:
class SelectCombo(QtWidgets.QComboBox):
def keyPressEvent(self, event):
# call the base class implementation
super().keyPressEvent(event)
# if return/enter is pressed, select the text afterwards
if event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
self.lineEdit().selectAll()
Ok, I've got it all assembled :) Problem was, I previously needed to define a shortcut since QComboBox does not have a returnPressed attribute.
With the custom widget, I can change that easily, of course:
class SelectCombo(QtWidgets.QComboBox):
'''
https://stackoverflow.com/questions/62594748/how-to-mark-current-item-text-in-qcombobox/62598381
Modified QComboBox which selects the current text after Enter/Return.
'''
returnPressed = QtCore.pyqtSignal(str)
def keyPressEvent(self, event):
## call the base class implementation
super().keyPressEvent(event)
## if return/enter is pressed, select the text afterwards
if event.key() in (QtCore.Qt.Key_Return, QtCore.Qt.Key_Enter):
self.lineEdit().selectAll()
self.returnPressed.emit("Enter pressed!")
And in my GUI app, I simply need the following signal-slot definition to make it work:
## 1) QLineEdit has "returnPressed" but no history
#self.lineEdit_cmd.returnPressed.connect(self.queryLine)
## 2) QComboBox has history, but no "returnPressed" attritbute==> need to define a shortcut
#QtCore.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return),
#QtWidgets.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Return),
# self.comboBox_cmd,
# activated=self.queryLine)
## 3) custom SelectCombo widget has QComboBox's history plus "returnPressed"
self.comboBox_cmd.returnPressed.connect(self.queryLine)
Thanks a lot for helping me!
I have two buttons (Eg. A andB) which do the same things (based on user selection). So when you select something, then click the button, the selection's name will be input into the line-edit for the button. For example, if I click on buttonA, the input will be to lineEditA.
Currently I have created a signal function as follows:
def _connections_setup(self):
self.btnA.clicked.connect(self.get_sel_nameA)
self.btnB.clicked.connect(self.get_sel_nameB)
def get_sel_nameA(self):
sel_name = get_name_from_sel()
self.line_editA.setText(sel_name)
def get_sel_nameB(self):
sel_name = get_name_from_sel()
self.line_editA.setText(sel_name)
"""
def get_sel_name(self):
# Returns me a blank
button = self.sender()
print button.objectName()
# My objective here would be, if btnA is clicked, the sel_name will be inputted into lineEditA. Likewise for btnB
"""
Instead of creating two similar functions, how can I determine which button was clicked and have the selection's name to be input correctly into the line-edit?
I tried using self.sender() (see get_sel_name()) but it does not seems to return me the button name.
The sender() function only works in slots directly connected to signals. So your code needs to look something like this:
def _connections_setup(self):
self.btnA.clicked.connect(self.get_sel_name)
self.btnB.clicked.connect(self.get_sel_name)
def get_sel_name(self):
button = self.sender()
name = button.objectName()
if button is self.btnA:
self.line_editA.setText(name)
elif button is self.btnB:
self.line_editB.setText(name)
I often see Tkinter applications initialize Menu widgets using tearoff=0 in the constructor.
import tkinter as tk
root = tk.Tk()
menubar = tk.Menu(root)
filemenu = tk.Menu(menubar, tearoff=0)
effbot.org's documentation for Menu specifies that the default value for tearoff is 1, but it doesn't explain what the value is used for.
tearoff=
Default value is 1. (tearOff/TearOff)
tearoffcommand=
No default value. (tearOffCommand/TearOffCommand)
What does the tearoff attribute do when initializing a tkinter Menu widget?
The official python docs admit that they're a little light on details:
The tkinter package is a thin object-oriented layer on top of Tcl/Tk. To use tkinter, you don’t need to write Tcl code, but you will need to consult the Tk documentation, and occasionally the Tcl documentation.
The Tk documentation for tearoff gives you what you're looking for:
tearoff allows you to detach menus for the main window creating floating menus. If you create a menu you will see dotted lines at the top when you click a top menu item. If you click those dotted lines the menu tears off and becomes floating.
Here you can see a tkinter Menu tear-off with the code for it in the background. I'm not sure how useful this is going to be but according to New Mexico Tech:
Normally, a menu can be torn off: the first position (position 0) in the list of choices is occupied by the tear-off element, and the additional choices are added starting at position 1. If you set tearoff=0, the menu will not have a tear-off feature, and choices will be added starting at position 0.
Try this if you want to test the floating menu if you are using Windows.
from tkinter import *
import re
class HoverInfo(Menu):
def __init__(self, parent, text, command=None):
self._com = command
Menu.__init__(self,parent, tearoff=1)
if not isinstance(text, str):
raise TypeError('Trying to initialise a Hover Menu with a non string type: ' + text.__class__.__name__)
toktext=re.split('\n', text)
for t in toktext:
self.add_command(label = t)
self._displayed=False
self.master.bind("<Enter>",self.Display )
self.master.bind("<Leave>",self.Remove )
def __del__(self):
self.master.unbind("<Enter>")
self.master.unbind("<Leave>")
def Display(self,event):
if not self._displayed:
self._displayed=True
self.post(event.x_root, event.y_root)
if self._com != None:
self.master.unbind_all("<Return>")
self.master.bind_all("<Return>", self.Click)
def Remove(self, event):
if self._displayed:
self._displayed=False
self.unpost()
if self._com != None:
self.unbind_all("<Return>")
def Click(self, event):
self._com()
class MyApp(Frame):
def __init__(self, parent=None):
Frame.__init__(self, parent)
self.grid()
self.lbl = Label(self, text='testing')
self.lbl.grid()
self.hover = HoverInfo(self, 'while hovering press return \n for an exciting msg', self.HelloWorld)
def HelloWorld(self):
print('Hello World')
app = MyApp()
app.master.title('test')
app.mainloop()
This example is Hover Class by Gogo. Display message when hovering over something with mouse cursor in Python
I Just set tear-off to 1 to see the floating effect.
By default, the choices in the menu start taking place from position 1. If we set the tearoff = 1, then it will start taking place from 0th position
I have a layout with 5 buttons which I act as "menus", so you click on one button and one view will show up, you click another button and another view shows up. I need to find out which button is clicked so I can do something based on which button is pressed. Something like
if button1_is_clicked:
do_something()
else:
do_something_else()
What would be the best way to approach this?
Here is my code:
I want to be able to change the stylesheet of the button, so an active state and a non-active state
from PySide import QtCore
from PySide import QtGui
import VulcanGui
#--------------------------------------------------------------------------
class Program(QtGui.QMainWindow, VulcanGui.Ui_MainWindow):
def __init__(self, parent=None):
""" Initialize and setup the User Interface """
super(Program, self).__init__(parent)
self.setupUi(self)
""" Populate the Main Area """
self.mainArea.setHtml(self.intro_text())
""" Button Signal/Slots """
self.introButton.toggled.connect(self.intro_area)
self.runVulcanButton.clicked.connect(self.vulcan_run_area)
self.vulcanLogButton.clicked.connect(self.vulcan_log_area)
self.hostFileButton.clicked.connect(self.edit_host_area)
self.configEditButton.clicked.connect(self.edit_config_area)
def intro_text(self):
content_file = open("../content/intro_text.html").read()
return content_file
'''
Get the content to print
'''
def intro_area(self):
content_file = open("../content/intro_text.html").read()
self.mainArea.setHtml(content_file)
'''
Function that will display the data when the 'Run Vulcan' button is pressed
'''
def vulcan_run_area(self):
self.mainArea.setPlainText("Button Two ")
'''
Function that will display the data when the 'Vulcan Log' button is pressed
'''
def vulcan_log_area(self):
self.mainArea.setPlainText("Button Three")
'''
Function that will display the data when the 'Edit Host File' button is pressed
'''
def edit_host_area(self):
self.mainArea.setPlainText("Button Four")
'''
Function that will display the data when the 'Edit Config File' button is pressed
'''
def edit_config_area(self):
self.mainArea.setPlainText("Button Five")
#--------------------------------------------------------------------------
if __name__ == "__main__":
import sys
program = QtGui.QApplication(sys.argv)
mWindow = Program()
mWindow.show()
sys.exit(program.exec_())
I suggest you learn the basics of Qt to get acquainted with signals and slots.
You need to make the initially visible QPushButtons checkable (otherwise the 'revealed' buttons will only appear whilst the button is held down), and connect the toggled(bool) signal to the setVisible(bool) slot of the buttons you want to 'reveal'. Obviously for the buttons that are initially invisible, you would have to call setVisible(false) upon instantiation.
There are other, more reusable, ways of achieving the same effect - but this will get you started.
I have a Tix.ComboBox with an editable text field. How do I force the variable holding the value for the text to update?
Let me give a more concrete explanation. I have a combo box and a button. When I click the button, it pops up a message box with the value of the combo box. Let's say the combo box text field currently has the value "thing1". If I type "new" into the box and then click on the button with my mouse, it will pops up the message "thing1". If I type "new" in the box and then tab focus away from the combo box and then click the button the pop up message says "new".
Ho do I force the combo box to update it's value to new without requiring that I tab away from the combo box?
I have included sample code.
import Tix
import tkMessageBox
class App(object):
def __init__(self, window):
window.winfo_toplevel().wm_title("test")
self.window = window
self.combo = Tix.ComboBox(window)
self.combo.insert(Tix.END, 'thing1')
self.combo.insert(Tix.END, 'thing2')
self.combo.entry['state'] = "normal"
self.combo['editable'] = True
self.combo.pack()
button = Tix.Button(window)
button['text'] = "Go"
button['command'] = self.go
button.pack()
def go(self):
tkMessageBox.showinfo('info', self.combo['value'])
if __name__ == '__main__':
root = Tix.Tk()
App(root)
root.mainloop()
woo!
solved it on my own.
Use
self.combo['selection']
instead of
self.combo['value']
NOTE: copy of Moe's answer that can be selected as chosen answer
woo!
solved it on my own.
Use
self.combo['selection']
instead of
self.combo['value']