Allowing TABs in Char Validator - python-2.7

Currently I have a data input screen where the user has to navigate between input fields using the mouse. I would like to add a TAB facility so that they can TAB between input fields, e.g. Last Name → First Name → DOB, etc. The input screen makes use of Validators to prevent users inputting nonsense:-
def OnChar(self, evt):
key = chr(evt.GetKeyCode())
if ord(key) in [wx.WXK_BACK, wx.WXK_DELETE]:
evt.Skip()
if self.flag == LETTERS and key not in string.letters:
return
if self.flag == DECIMAL_DIGITS and key not in string.digits:
return
if self.flag == HEX_DIGITS and key not in string.hexdigits:
return
if self.flag == ALPHA_NUMERIC and key not in string.printable:
return
evt.Skip()
I have added:-
style=wx.TAB_TRAVERSAL | wx.DEFAULT_DIALOG_STYLE
to the Frame. However the Validator traps the TABs. Is there a way to get around this problem?

Because you are converting the key to chr() it is not recognising wx.WXK_TAB see the following to demonstrate your problem:
#!/usr/bin/python
# -*- coding: utf-8 -*-
import wx
class Example(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, wx.ID_ANY, "Tab Key Test",size=(310,120))
self.Stop_prog = False
self.top = wx.Panel(self, wx.ID_ANY)
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.text_input = wx.TextCtrl(self.top, wx.ID_ANY, size=(300,25))
self.sizer.Add(self.text_input)
self.text_input.Bind(wx.EVT_KEY_DOWN, self.OnKey)
self.top.Sizer = self.sizer
self.top.Sizer.Fit(self.top)
self.Show()
def OnKey(self,event):
print "Key Pressed", event.GetKeyCode()
keycode = event.GetKeyCode()
try:
charkey = chr(event.GetKeyCode())
print "Character Key", charkey
except:
print "unable to convert key to a character in the range 256"
if keycode == wx.WXK_F1:
self.Close()
elif keycode == wx.WXK_TAB:
print "TAB"
self.text_input.SetValue("You pressed Tab")
else:
event.Skip()
def main():
ex = wx.App()
Example(None)
ex.MainLoop()
if __name__ == '__main__':
main()

Related

How can i disable the selection highlighted green in table widget using pyqt4

Here is my sample code.I need to remove green highlighted selection in my table widget for that i wrote QtGui.QAbstractItemView.NoSelection but using this line i am not able to move my cursor up,down ,left and right in table widget.Can any one please tell me how to disable the green selection and i want to move my cursor using with arrow keys in keyboard..Please help me..Thank you in advance..
Given below is my code:
import sys
from PyQt4 import QtCore,QtGui
global data_arraylist,count,pushBtnList,lineeditList
class Table_Program(QtGui.QMainWindow ):
def __init__(self,config=None, parent=None):
super(Table_Program, self).__init__(parent)
global data_arraylist,count,pushBtnList,lineeditList
self.scrollArea_left = QtGui.QScrollArea(widgetResizable=True)
self.mainw2 = QtGui.QWidget()
self.mainw2.showFullScreen()
self.scrollArea_left.setWidget(self.mainw2)
self.newvbox = QtGui.QGridLayout(self.mainw2)
self.table = QtGui.QTableWidget()
self.table_item = QtGui.QTableWidgetItem()
self.table.setRowCount(1)
self.table.verticalHeader().hide()
self.table.setColumnCount(4)
self.table.setHorizontalHeaderLabels(("S.no, Item Description,Qty,Rate(Rs:),"",").split(','))
self.newvbox.addWidget(self.table,0,0)
self.table.setColumnWidth(2,170)
self.table.setColumnWidth(3,200)
self.btn1 = QtGui.QPushButton(icon=QtGui.QIcon("./plus1.png"))
self.btn1.setIconSize(QtCore.QSize(30,20))
self.table.setCellWidget(0,0,self.btn1)
self.btn1.clicked.connect(self.insert_rows)
self.table.setItem(0,4,QtGui.QTableWidgetItem(str(" ")))
self.setCentralWidget(self.scrollArea_left)
# QtGui.QShortcut(QtGui.QKeySequence(QtCore.Qt.Key_Up), self, self.moveup)
def insert_rows(self,typ=None):
layout_item = QtGui.QHBoxLayout()
cellWidget = QtGui.QWidget()
self.itemlineedit = QtGui.QLineEdit()
self.itemlineedit.setFrame(False)
self.search_btn = QtGui.QPushButton(icon=QtGui.QIcon('search.png'))
self.search_btn.setIconSize(QtCore.QSize(20,20))
layout_item.addWidget(self.itemlineedit)
layout_item.addStretch()
layout_item.addWidget(self.search_btn)
cellWidget.setLayout(layout_item)
global pushBtnList
ct = self.table.rowCount()
self.table.insertRow(ct-1)
self.btn = QtGui.QPushButton()
self.btn.setIcon(QtGui.QIcon("./delete.png"))
self.btn.setIconSize(QtCore.QSize(30,60))
self.table.setItem(ct-1,0,QtGui.QTableWidgetItem(str(ct)))
self.table.setCellWidget(ct -1,5,self.btn)
index = QtCore.QPersistentModelIndex(self.table.model().index(ct -1, 5))
self.quantybutton = QtGui.QLineEdit()
self.itemlineedit.textChanged.connect(partial(self.product_rate,ct))
completer = QtGui.QCompleter()
self.itemlineedit.setCompleter(completer)
self.model = QtGui.QStringListModel()
self.itemlineedit.resize(100,50)
completer.setModel(self.model)
self.item_rate = QtGui.QLabel()
self.table.setCellWidget(ct-1, 3,self.item_rate)
self.table.setCellWidget(ct-1, 2, self.quantybutton)
self.table.setCellWidget(ct -1, 1, cellWidget)
self.table.setRowHeight(ct-1,50)
self.table.setColumnWidth(1,170)
def get_data(self,model):
model.setStringList(["item1","item2","item3"])
def product_rate(self,text,index):
self.quantybutton.setText("1")
self.item_rate.setText(str("20"))
self.get_data(self.model)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
tb = Table_Program()
tb.show()
tb.resize(600,300)
sys.exit(app.exec_())
A simple solution is to implement a custom QStyle that disables the highlight option in the QTableWidget:
from PyQt4 import QtCore, QtGui
class CustomStyle(QtGui.QCommonStyle):
def drawPrimitive(self, element, option, painter, widget):
if element == QtGui.QStyle.PE_PanelItemViewItem:
option.state &= ~QtGui.QStyle.State_Selected
super(CustomStyle, self).drawPrimitive(element, option, painter, widget)
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
w = QtGui.QTableWidget(5, 4)
w.setStyle(CustomStyle()) # <--- set style
w.show()
sys.exit(app.exec_())

Using Python Tkinter .config() method

I am trying to use the Python Tkinter .config() method to update some message text. I can't get it to work. What might I be doing wrong (see the update_message method):
#!/usr/bin/python
import alsaaudio as aa
import audioop
import Tkinter as tk
import tkFont
import threading
import Queue
# styles
BACKROUND_COLOR = '#000000'
TYPEFACE = 'Unit-Bold'
FONT_SIZE = 50
TEXT_COLOR = '#777777'
TEXTBOX_WIDTH = 400
# text
TITLE = 'listen closely'
SCORE_MESSAGE = 'your score:\n '
END_MESSAGE = 'too loud!\ntry again'
# configuration
DEVICE = 'hw:1' # hardware sound card index
CHANNELS = 1
SAMPLE_RATE = 8000 # Hz // 44100
PERIOD = 256 # Frames // 256
FORMAT = aa.PCM_FORMAT_S8 # Sound format
NOISE_THRESHOLD = 3
class Display(object):
def __init__(self, parent, queue):
self.parent = parent
self.queue = queue
self._geom = '200x200+0+0'
parent.geometry("{0}x{1}+0+0".format(
parent.winfo_screenwidth(), parent.winfo_screenheight()))
parent.overrideredirect(1)
parent.title(TITLE)
parent.configure(background=BACKROUND_COLOR)
parent.displayFont = tkFont.Font(family=TYPEFACE, size=FONT_SIZE)
self.process_queue()
def process_queue(self):
try:
score = self.queue.get(0)
self.print_message(score)
except Queue.Empty:
pass
self.parent.after(100, self.update_queue)
def update_queue(self):
try:
score = self.queue.get(0)
self.update_message(score)
except Queue.Empty:
pass
self.parent.after(100, self.update_queue)
def print_message(self, messageString):
print 'message', messageString
displayString = SCORE_MESSAGE + str(messageString)
self.message = tk.Message(
self.parent, text=displayString, bg=BACKROUND_COLOR,
font=self.parent.displayFont, fg=TEXT_COLOR, width=TEXTBOX_WIDTH, justify="c")
self.message.place(relx=.5, rely=.5, anchor="c")
def update_message(self, messageString):
print 'message', messageString
displayString = SCORE_MESSAGE + str(messageString)
self.message.config(text=displayString)
def setup_audio(queue, stop_event):
data_in = aa.PCM(aa.PCM_CAPTURE, aa.PCM_NONBLOCK, 'hw:1')
data_in.setchannels(2)
data_in.setrate(44100)
data_in.setformat(aa.PCM_FORMAT_S16_LE)
data_in.setperiodsize(256)
while not stop_event.is_set():
# Read data from device
l, data = data_in.read()
if l:
# catch frame error
try:
max_vol = audioop.rms(data, 2)
scaled_vol = max_vol // 4680
print scaled_vol
if scaled_vol <= 3:
# Too quiet, ignore
continue
queue.put(scaled_vol)
except audioop.error, e:
if e.message != "not a whole number of frames":
raise e
def main():
root = tk.Tk()
queue = Queue.Queue()
window = Display(root, queue)
stop_event = threading.Event()
audio_thread = threading.Thread(target=setup_audio,
args=[queue, stop_event])
audio_thread.start()
try:
root.mainloop()
finally:
stop_event.set()
audio_thread.join()
pass
if __name__ == '__main__':
main()
I don't want to be laying down a new message every time I update. If the .config() doesn't work, is there another method to update the text configuration of the message?
I would use string variables, first create your string variable then set it to want you want it to display at the start next make your object and in text put the sting variable then when you want to change the text in the object change the string variable.
self.messaget = StringVar()
self.messaget.set("")
self.message = tk.Message(
self.parent, textvariable=self.messaget, bg=BACKROUND_COLOR,
font=self.parent.displayFont, fg=TEXT_COLOR,
width=TEXTBOX_WIDTH, justify="c").grid()
#note renember to palce the object after you have created it either using
#.grid(row = , column =) or .pack()
#note that it is textvariable instead of text if you put text instead it will run but
#but will show PY_Var instead of the value of the variable
edit
to change the text without recreating the object you do the name of the string variable you have used and .set
self.messaget.set("hi")

Setting and Retrieving Data with TkInter

I just ran into some strange behavior that has me stumped. I'm writing a simple little GUI for some in-house data processing. I want to allow a user to switch between a few different data-processing modes and input some parameters which define how the data is processed for each mode. The problem is that when the user inputs new parameters, the app ignores requests to switch modes.
The code below replicates the issue. I apologize for the size, this was the shortest code that replicates the problem.
import Tkinter as Tk
class foo(Tk.Frame):
def __init__(self):
self.master = master =Tk.Tk()
Tk.Frame.__init__(self,self.master) #Bootstrap
#Here mode and parameters as key, value pairs
self.data = {'a':'Yay',
'b':'Boo'
}
self.tex = Tk.Text(master=master)
self.tex.grid(row=0,column=0,rowspan=3,columnspan=4)
self.e = Tk.Entry(master=master)
self.e.grid(row=3,column=0,columnspan=4)
self.sv =Tk.StringVar()
self.sv.set('a')
self.b1 = Tk.Radiobutton(master=master,
text = 'a',
indicatoron = 0,
variable = self.sv,
value = 'a')
self.b2 = Tk.Radiobutton(master=master,
text = 'b',
indicatoron = 0,
variable = self.sv,
value = 'b')
self.b3 = Tk.Button(master = master,
text='Apply',command=self.Apply_Func)
self.b4 = Tk.Button(master = master,
text='Print',command=self.Print_Func)
self.b1.grid(row=4,column=0)
self.b2.grid(row=4,column=1)
self.b3.grid(row=4,column=2)
self.b4.grid(row=4,column=3)
def Apply_Func(self):
self.innerdata = self.e.get()
def Print_Func(self):
self.tex.insert(Tk.END,str(self.innerdata)+'\n')
#This is how I'm retrieving the user selected parameters
#property
def innerdata(self):
return self.data[self.sv.get()]
#And how I'm setting the user defined parameters
#innerdata.setter
def innerdata(self,value):
self.data[self.sv.get()] = value
if __name__ == "__main__":
app = foo()
app.mainloop()
Expected behavior:
1) Press button 'a' then 'print' prints:
Yay
2) Press button 'b' then 'print' prints:
Boo
3) Type 'Zep Rocks' into the entry field and press apply
4) Pressing 'print' now yields
Zep Rocks
5) Pressing 'a' then 'print' should yield
Yay
But instead yields
Zep Rocks
Which might be true, but not desired right now. What is going on here?
Edit: I have some new information. Tk.Frame in python 2.7 is not a new-style class. It isn't friendly with descriptors, so rather than interpreting the '=' as a request to use the foo.innerdata's __set__ method, it just assigns the result of self.e.get() to innerdata.
ARGLEBARGLE!!!
Still an open question: how do I get this to do what I want in a clean manner?
So the core problem is that Tk.Frame doesn't subclass from object, so it is not a new-style python class. Which means it doesn't get down with descriptors like I was trying to use. One solution that I found is to subclass my app from object instead.
Code that solves my problem is below:
import Tkinter as Tk
class foo(object):
def __init__(self,master):
self.master = master #Bootstrap
self.mainloop = master.mainloop
self.data = {'a':{'value':7,'metavalue':False},
'b':{'value':'Beeswax','metavalue':True}
}
self.tex = Tk.Text(master=master)
self.tex.grid(row=0,column=0,rowspan=3,columnspan=4)
self.e = Tk.Entry(master=master)
self.e.grid(row=3,column=0,columnspan=4)
self.sv =Tk.StringVar()
self.sv.set('a')
self.b1 = Tk.Radiobutton(master=master,
text = 'a',
indicatoron = 0,
variable = self.sv,
value = 'a')
self.b2 = Tk.Radiobutton(master=master,
text = 'b',
indicatoron = 0,
variable = self.sv,
value = 'b')
self.b3 = Tk.Button(master = master,text='Apply',command=self.Apply_Func)
self.b4 = Tk.Button(master = master,text='Print',command=self.Print_Func)
self.b1.grid(row=4,column=0)
self.b2.grid(row=4,column=1)
self.b3.grid(row=4,column=2)
self.b4.grid(row=4,column=3)
def Apply_Func(self):
self.innerdata = self.e.get()
def Print_Func(self):
self.tex.insert(Tk.END,str(self.innerdata)+'\n')
#property
def innerdata(self):
return self.data[self.sv.get()]
#innerdata.setter
def innerdata(self,value):
self.data[self.sv.get()] = value
if __name__ == "__main__":
master = Tk.Tk()
app = foo(master)
app.mainloop()

Pygame midi prevents other input

I wish to have real-time midi input, in order to control some wx.Sliders. I have been able to achieve this, however it prevents interaction with the sliders via the mouse or keyboard and causes the application to crash.
This is the code I have at the moment.
import wx, pygame, pygame.midi
class windowClass(wx.Frame):
def __init__(self, *args, **kwargs):
super(windowClass, self).__init__(*args, **kwargs)
self.basicGUI()
def basicGUI(self):
panel = wx.Panel(self)
self.slider = wx.Slider(panel, -1, 2, 0, 128, pos=(10,25), size=(250,-1), style=wx.SL_AUTOTICKS | wx.SL_LABELS)
sliderText = wx.StaticText(panel, -1, 'Slider 1 ', (8,8))
self.slider2 = wx.Slider(panel, -1, 2, 0, 128, pos=(10,110), size=(250,-1), style=wx.SL_AUTOTICKS | wx.SL_LABELS)
sliderText = wx.StaticText(panel, -1, 'Slider 2', (8,88))
self.Bind(wx.EVT_SLIDER, self.sliderUpdate)
self.SetTitle('Sliders Window!')
self.Show(True)
pygame.init()
pygame.midi.init()
inp = pygame.midi.Input(1)
running = True
while running:
if inp.poll():
dataset = inp.read(1)
control = dataset[0][0][1]
if control > 8:
continue
if control == 1:
value = dataset[0][0][2]
self.slider.SetValue(value)
if control == 2:
value = dataset[0][0][2]
self.slider2.SetValue(value)
pygame.time.wait(10)
def sliderUpdate(self, event):
value1 = self.slider1.GetValue()
value2 = self.slider2.GetValue()
print value1, value2
def main():
app = wx.App()
windowClass(None)
app.MainLoop()
main()
What is causing pygame.midi to take all resources? I have a feeling it is regarding while running = True, however my attempts at trying to close the instance don't seem to work.
How can I have the sliders being controlled by the midi and the mouse calling sliderUpdate? Thanks for any help.
You have a loop that never exits, so your program never reaches the parts that deal with anything except the midi input
I would move the code that is currently in that loop into a function, remove the loop, and add a timer to the panel, e.g.
def basicGUI(self):
... panel stuff
pygame.init()
pygame.midi.init()
timer = wx.Timer(self, -1)
self.Bind(wx.EVT_TIMER, self.OnTimer)
timer.Start(10, False)
def OnTimer(self, event):
inp = pygame.midi.Input(1)
if inp.poll():
dataset = inp.read(1)
control = dataset[0][0][1]
if control > 8:
continue
if control == 1:
value = dataset[0][0][2]
self.slider.SetValue(value)
if control == 2:
value = dataset[0][0][2]
self.slider2.SetValue(value)

PySide, QTextEdit Append adding blank lines

I have this simple code: basically a tool to send some commands to cmd, and display the output from cmd in a QTextEdit.
Basically, it works.
The only problem that I have is that each time I click on send (with or without a new command), the text is appended but strange blank lines appears at the end of the QTextEdit. Even when i clear the "console", still have these lines.
Maybe it has something to do with the way I call the process, I don't know hence the need for help.
from PySide.QtCore import *
from PySide.QtGui import *
import sys
class MyWindow(QDialog):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.setWindowTitle("Send to CMD")
self.check1 = QCheckBox("Activate Variable")
self.variable = QLineEdit()
self.finalcommand = QLineEdit()
self.clearCommand = QPushButton("Clear")
self.sendCommand = QPushButton("Send")
self.clearOnSend = QCheckBox("Clear on Send")
self.process = QProcess()
self.console = QTextEdit(self)
layout = QVBoxLayout()
layout.addWidget(self.check1)
layout.addWidget(self.variable)
layout.addWidget(self.finalcommand)
layout.addWidget(self.clearOnSend)
layout.addWidget(self.clearCommand)
layout.addWidget(self.sendCommand)
layout.addWidget(self.console)
self.setLayout(layout)
self.connect(self.check1, SIGNAL("clicked()"), self.appendText)
self.variable.textChanged.connect(self.appendText)
self.clearCommand.clicked.connect(self.Clear)
self.sendCommand.clicked.connect(self.Send)
def appendText(self):
if self.check1.isChecked():
TEXT1 = "Dir" + ' ' + str(self.variable.text())
else:
TEXT1 = ""
self.finalcommand.setText(str(TEXT1))
def Clear(self):
if self.clearCommand.isEnabled():
self.console.clear()
def Send(self):
if self.clearOnSend.isChecked():
self.console.clear()
FCTS = "cmd.exe /c" + " " + str(self.finalcommand.text())
self.process.readyReadStandardOutput.connect(self.readConsole)
self.process.start(FCTS)
if not self.process.waitForStarted(0):
return False
if not self.process.waitForFinished(0):
return False
def readConsole(self):
#self.console.setText(str(self.process.readAllStandardOutput()))
self.console.append(str(self.process.readAllStandardOutput()))
app = QApplication(sys.argv)
form = MyWindow()
form.show()
app.exec_()
You probably want to use the string.rstrip() function instead of string.strip()
if you change
self.console.append(str(self.process.readAllStandardOutput()))
to
self.console.append(str([self.process.readAllStandardOutput()]))
you can see what is going on, hope this helps
def appendText(self):
if self.check1.isChecked():
TEXT1 = "Dir" + ' ' + str(self.variable.text())
else:
TEXT1 = ""
you have to remove the last line after else and just type pass
this way no new empty lines will be appended
def appendText(self):
if self.check1.isChecked():
TEXT1 = "Dir" + ' ' + str(self.variable.text())
else:
pass