Tkintertable Get selected Data - python

I'm using tkintertable and want to check which row is selected. Is this possible?
And I also want to sort the columns and name the columns like I want...
How can I do this?

I'm a little late, but figured I would answer this in case anyone else finds this through a google search like I did :P
There are a couple ways to do select data based on mouse clicks.
First you need to bind the mouse click to a callback function, and in this callback function you need to grab the data. You might need to bind the mouse click on release so that it grabs data when you release the mouse button.
You can use the table.get_row_clicked()/table.get_col_clicked() functions along with model.getValueAt() to do get individual cells.
To get the contents of an entire row in a dictionary where column_name = key & contents of that selected rows column = value, you need to use model.getRecordAtRow(row_index).
Example:
from Tkinter import *
from ttk import *
from tkintertable.Tables import TableCanvas
from tkintertable.TableModels import TableModel
class Application(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.model = TableModel()
self.table = TableCanvas(self, model=self.model)
self.table.createTableFrame()
root.bind('<ButtonRelease-1>', self.clicked) #Bind the click release event
self.create_widgets()
def create_widgets(self):
self.table.model.load('save.table') #You don't have to load a model, but I usually
self.table.redrawTable() #Create a base model for my tables.
d = dir(self.table) #Will show you what you can do with tables. add .model
#to the end to see what you can do with the models.
for i in d:
print i
def clicked(self, event): #Click event callback function.
#Probably needs better exception handling, but w/e.
try:
rclicked = self.table.get_row_clicked(event)
cclicked = self.table.get_col_clicked(event)
clicks = (rclicked, cclicked)
print 'clicks:', clicks
except:
print 'Error'
if clicks:
#Now we try to get the value of the row+col that was clicked.
try: print 'single cell:', self.table.model.getValueAt(clicks[0], clicks[1])
except: print 'No record at:', clicks
#This is how you can get the entire contents of a row.
try: print 'entire record:', self.table.model.getRecordAtRow(clicks[0])
except: print 'No record at:', clicks
root = Tk()
root.title('Table Test')
app = Application(master=root)
print 'Starting mainloop()'
app.mainloop()
As far as the other things, you should be able to get info off the wiki:
http://code.google.com/p/tkintertable/wiki/Usage
Some things are a pain to figure out, but it's worth it IMO. I still can't figure out how to programmatically change the contents of a cell, and that's right on the wiki page, lol.

Related

Best way to replace Window in Toga (Beeware)

I'm currently trying to create a cross platform app with Beeware using Toga.
I konw how to update the content in a window (I just empty everything in the box and add new content to it).
But now I have the problem that I want to add entry fields which need to be assigned to a variable so I can get the value of them (And my class for the first window is already very big... so I don't want to add new properties and methods too it). So my intention was to create a new class besides my other class which displays my new window and closes the old one (or just replaces my old one)
E. g.:
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
class FirstWindow(toga.App):
def startup(self):
main_box = toga.Box(style=Pack(direction=COLUMN))
main_box.add(toga.Button('Open window 2', on_press=self.open_new_window))
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
def open_new_window(self, widget):
# This should close the current Window and display the other window
# return SecodnWindow() doesn't work
# close() and exit() doesn't work too, cause I can't execute code after this
# statements anymore
class SecondWindow(toga.App):
def startup(self):
main_box = toga.Box(style=Pack(direction=COLUMN))
#adding all the stuff to the window
self.main_window = toga.MainWindow(title=self.formal_name)
self.main_window.content = main_box
self.main_window.show()
# Other code
def main():
return FirstWindow()
Thanks ^^
I found a solution:
import toga
from toga.style import Pack
from toga.style.pack import COLUMN, ROW
class MultiWindow(toga.App):
def startup(self):
main_box = toga.Box()
main_box.add(toga.Button('Open Window', on_press=self.show_second_window))
self.main_window = toga.Window(title=self.formal_name, closeable=True)
self.main_window.content = main_box
self.main_window.show()
def show_second_window(self, widget):
outer_box = toga.Box()
self.second_window = toga.Window(title='Second window')
self.windows.add(self.second_window)
self.second_window.content = outer_box
self.second_window.show()
self.main_window.close()
def main():
return MultiWindow()
Sadly it's all in one class but I will try to improve it
Note: In this solution it is not possible to have a main window. As soon as you close the main window the app will close. When you just want to have a second window without closing the main window you can still use a main window.
If I find better solutions I will update this gist:
https://gist.github.com/yelluw/0acee8e651a898f5eb46d8d2a577578c

Qt get action clicked from submenu

I got a menu opening when right clicking on a table, I'd like to get the action name I clicked on. The thing is that I create actions in a loop. Basically each action add the right clicked item to a file (a playlist). So in order to add the item I need to know where.
def menu(self, event):
self.menu_table = QtWidgets.QMenu(self.tableWidget)
self.submenu = QtWidgets.QMenu("Add to a playlist")
list = os.listdir("playlists")
for i in list:
self.submenu.addAction(i)
self.submenu.triggered.connect(MyFunction(ItemClicked))
self.menu_table.addMenu(self.submenu)
self.menu_table.exec_(self.tableWidget.mapToGlobal(event))
Your context menu handler should look like this:
def menu(self, pos):
menu = QtWidgets.QMenu()
submenu = menu.addMenu("Add to a playlist")
for filename in os.listdir("playlists"):
submenu.addAction(filename)
action = menu.exec_(self.mapToGlobal(pos))
if action is not None:
print(action.text())
MyFunction(action)
As mentioned, the menu's exec call returns the selected action. What would probably be easiest for you is to use QAction.setData to store the information you need into each action. It's a QVariant, so you can store practically anything. Then, in the result of the "exec" call, you use the selected action's QAction.data to get the value back out. (Sorry if my syntax isn't right...I don't know much Python.)

How can I update Entry without a "submit" button in Tkinter?

So I have Entries which have some values assigned to them from a CFG File. I want to modify the CFG file when the Entry is updated, live, without a submit button;
Using <Key> binding will work but will take only the previous value, not the current one, as the last key pressed is not taken into consideration as a value, but as a key-press.
For example:
class EntryBox:
def __init__(self, value, option, section, grid_row, master_e):
self.section = section
self.option = option
self.box = Entry(master_e)
self.box.grid(column=0, row=grid_row)
self.serial_no = grid_row
self.box.insert(0, value)
self.box.bind("<Key>", lambda event: update_cfg(event, self, self.get_value()))
def get_value(self):
return self.box.get()
def update_cfg(evt, entry_box,new_value):
global config_file
config_file.set(entry_box.section, entry_box.option, new_value)
print "Config file modified. "+entry_box.section+" "+entry_box.option+" "+new_value
If the value in the entry is 05R when I click on the entry and press 6, it will print Config file modified. CURRENT_MEASUREMENT_EXAMPLE_HP shunt_resistance 05R; after I press 7, it will print Config file modified. CURRENT_MEASUREMENT_EXAMPLE_HP shunt_resistance 0R56 and so on, always with one keypress behind. The only way to live update it after the value has been changed is to press the TAB or arrow buttons.
You can use either
FocusOut
tab or enter Key
KeyRelease
bindings to achieve that.
Also validation functions can help as they have previous and new values available. Please read the docs for more information on that matter.
It is IMHO the most "pythonic" / "tkinter" way of achieving what is a "check and submit" functionality.
Edit
As stated by OP, binding focusout could lead to problems here an example how it does indeed work:
import Tkinter as tk
import sys
def focus_out_event(event):
print >> sys.stderr, "Focus-Out event called with args: %s"%event
print >> sys.stderr, "Entry Widget Content: %s"%event.widget.get()
def key_release_event(event):
print >> sys.stderr, "Key-Release event called with args: %s"%event
print >> sys.stderr, "Entry Widget Content: %s"%event.widget.get()
if __name__ == "__main__":
root = tk.Tk()
entry1 = tk.Entry(root)
entry1.bind("", key_release_event)
entry1.bind("", focus_out_event)
entry1.grid()
entry2 = tk.Entry(root)
entry2.bind("", key_release_event)
entry2.bind("", focus_out_event)
entry2.grid()
root.mainloop()
Test:
- enter text ("asd") to entry1
- click into entry2
The last line of output is from changing to screenshot (event that fired a focusout)
You have this key-press in event.char so you can add it to text.
I decided that <Key> was not the right option in my case and instead used <FocusOut>. This way, if you either change the value using the mouse or keyboard TAB, on focus out it will update it.

.GetValue() is not working for TextCtrl in this particular case

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.

PyQt4 QComboBox Signals and Slots

is there a way to create a signal that asserts when a combo box is opened and user uses the up - down arrows on the keyboard to select an item. So far the Qt4 reference lists signals that activate only after a mouse click or return key hit. I tried highlighted(int) and that only worked with another mouse click but when i use the up/down arrows, only the first item that was clicked is retrieved. I thought the current highlighted index is the one that is returned via self.ui.cb_dspBenchCmds.currentText().
here's a code snippet:
class CmdRef(Qg.QMainWindow):
def __init__(self,parent = None):
........
Qc.QObject.connect(self.ui.cb_dspBenchCmds, Qc.SIGNAL("activated(int)"), self.chooseCmd)
........
def chooseCmd(self):
whichCmd = self.ui.cb_dspBenchCmds.currentText()
cmdDescription = self.dictDspCmds[str(whichCmd)]
self.ui.te_dspBenchOutput.setText(''.join(cmdDescription))
thanks
dave
The highlighted signal does appear to be the one you want.
You just need to make use of the passed value:
class CmdRef(Qg.QMainWindow):
def __init__(self, parent = None):
...
self.ui.cb_dspBenchCmds.highlighted['QString'].connect(self.chooseCmd)
...
def chooseCmd(self, whichCmd):
cmdDescription = self.dictDspCmds[str(whichCmd)]
self.ui.te_dspBenchOutput.setText(''.join(cmdDescription))

Categories