Welcome!
This is the community forum for my apps Pythonista and Editorial.
For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.
A touch event on a tableview?
-
Got a tableview working just fine, displays the data and allows selection of any given row.
Next, I've been searching for some kind of an example of how you might attach a function to when a tableview gets touched or row gets selected. I want to display a tableview of some items and when any particular one is touched, I pop up a dialog with details on the item. Would that be done with an event, a callback, or ??? Attached as a callback on the select? In any case, if something like that's possible I need a lead as to how it would be done...
Another option would be to allow the usual tableview row select capability, then also have a button on the top of the view that would check to see what row is selected and pop up the details from that. But I've not seen how you might add a button to a tableview.
-
You have a few options.
First, you can add your own buttons in the content_view, if you have a custom datasource. See for example
https://github.com/jsbain/gitview/blob/master/gitui.pyIt is also possible to add the cell "context menu" -- the menu that shows when you slide to the left. I believe I did this somewhere but can't find it now. There is an objc version, a version where you just rename the Delete button, and a version using a scrollview to simulate the effect using pure python classes...
-
@zinc ahh, I see you just want more detail...
A few options there. First you can implement the existing
tableview_accessory_button_tapped
In your delegate. You need to set the accessory_type as appropriate, and I think something at the tableview level. You can also define detail_text, and one of the other accessory types that lets you expand the detail, though you don't have much control over the formatting.https://forum.omz-software.com/topic/1524/simple-demo-of-tableview-logic-for-the-novices/7
-
Another example
https://github.com/jsbain/viewbrowser
This uses a navigation view, and so info buttons push a new view onto the stack, and then the back button pops off to where you were before. -
Hmm... some interesting examples, though pretty complex-- but thanks.
The context menu with the delete is an interesting idea-- I didn't know it was there. It raises the question though, I presume that delete just deletes it from the view and not the underlying datasource. I'm populating the tableview from a SQLite DB, and I'd love it if I could actually edit the data in the tableview, whether that's deleting rows or adding them.
The other question that has come up is that right now, I've just got a single string per row in the view, but the data has 4 columns. The example I found just concatenated individual strings together to make a "row" for the tableview, but given padding them to align columns is problematic the way the proportional font is displaying them, I'd actually like the tableview to have 4 cells across so that they would stay aligned, and if an edit was possible, would want that to be on a cell level... The delete could delete the entire row, but I don't know that any of this is within the scope of Pythonista and Tableviews. Seems to me, an event or callback triggered by an action on the tableview would be the easiest to work with, so if a delete event is done, I could then propagate the delete to the underlying database so that it's in sync with the view...
At any rate, I'll stare at your examples, as I'm sure I'll be able to learn something there.
-
@zinc, for your original request, would not just popping up a dialog with the
dialogs
module suffice? Called fromtableview_did_select
, which needs to be decorated with@ui.in_background
if you need the dialog to return a value (it’s a quirk).For breaking rows into cells, that gets a lot more complex but is certainly feasible. Grand master @cvp implemented an example for someone couple of months ago, but I just can’t find the post, maybe he can.
-
@mikael said:
Grand master
I suppose that you use "grand" like we use it in grandpa's and that it means old 😂.
And also that "master" is a typing error.But, anyway, even if I don't remember this post, it is really not complex to split cell content view in several subviews like labels. If your datasource item is a tuple, each element could be set as these label texts. Of course, only if I correctly understood the request.
-
Something like
?
If yes, I'll try to extract the needed code from my (huge) script...
-
I think you understood-- but I realized that some of my content is too wide to fit that way, so I decided to have the initial tableview just display the "key" column, and then used mikael's suggestion of using tableview_did_select to pop up a list dialog with the details. That's now working great. That's probably enough for my immediate needs, though having it integrated with some kind of edit functionality of individual items would be a nice feature-- at the moment I've got a separate script that just prompts with input() and writes to the DB. Gets the job done but isn't particularly pretty. Fortunately, I don't need to add that often so I can live with it as a separate script, but it does give me some food for thought on how to integrate it with the data viewer.
An edit feature would want to happen in the list dialog, and if that's not capable of doing it, I suppose it could be done by constructing my own list dialog from an additional popup table view, once I figure out how to do the edit. I probably don't need a delete, just an insert and an update operation. I see that tableview objects do support some form of editing. If you know of an example that demonstrates a tableview with edit capability (changing of row content, not just a delete), that would be educational and I could try it to see if it's the kind of thing that'll work for me.
Barring that, I'll probably play around with an edit-enabled tableview and see how it behaves...
Thanks for the tips gang...
-
@zinc if you use form_dialog instead of list_dialog, each field is editable
-
I wrote my last comment while you were posting yours-- that's an interesting looking example, stripped down to something not too huge that could be pretty interesting-- I could use it to display more than just the "key" column, and save the oversize column for the detail popup (my last column is a "notes" column where it can be anything from a null to a couple of sentences, to big to squeeze in a columnar format but the other columns would work nice in a grid like that...
I also spotted some comments in the documentation that implied that if the data source is properly hooked up to the tableview, in an edit mode it could propagate the view changes back to the database? Or that is, could be made to do that. I'll have to look more into that as well...
-
Personally, I use my own TableView, each row is a record of my dB and each subview is a label in the title row and a TextField in the other rows.
-
@zinc not extracted from my big script, but very quick,and dirty script where you can edit each field of each row
Of course, you will need your own process of TextFields, updating your dbimport ui def tableview_cell_for_row(tableview, section, row): # Create and return a cell for the given section/row cell = ui.TableViewCell() flds = tableview.data_source.items[row] w = tableview.width/len(flds) h = tableview.row_height x = 0 for fld in flds: tf = ui.TextField() tf.border_width = 1 tf.border_color = 'lightgray' tf.frame = (x,0,w,h) tf.text = fld cell.content_view.add_subview(tf) x += w return cell tv = ui.TableView() tv.frame = (0,0,400,500) tv.row_height = 32 db = [('1','2','3'),('4','5','6'),('7','8','9')] tv.data_source = ui.ListDataSource(items=db) tv.data_source.tableview_cell_for_row = tableview_cell_for_row tv.present('sheet')
-
On this case, you don't need a popup for editing and your note field can even be bigger than the frame, you will see the left part and if you tap on it for edition, you can reach the entire text
-
@zinc better
import ui def tableview_cell_for_row(tableview, section, row): # Create and return a cell for the given section/row cell = ui.TableViewCell() flds = tableview.data_source.items[row] w = tableview.width/len(flds) h = tableview.row_height x = 0 for fld in flds: tf = ui.TextField() tf.border_width = 1 tf.border_color = 'lightgray' tf.frame = (x,0,w,h) tf.text = fld cell.content_view.add_subview(tf) x += w return cell v = ui.View() v.frame = (0,0,400,500) v.background_color = 'white' keys = ('key 1','key 2','key 3') x = 2 w = (v.width-4)/len(keys) for key in keys: b = ui.Button() b.frame = (x,0,w,32) b.corner_radius = 8 b.background_color = 'lightgray' b.border_width = 1 b.border_color = 'gray' b.title = key v.add_subview(b) x += w tv = ui.TableView() tv.frame = (2,32,v.width-4,v.height) tv.row_height = 32 db = [('1','2','3')]*50 tv.data_source = ui.ListDataSource(items=db) tv.data_source.tableview_cell_for_row = tableview_cell_for_row v.add_subview(tv) v.present('sheet')
-
@mikael that comment about the quirk with @ui.in_background on tableview_did_select is a lifesaver! I have been pulling my hair out for about 3 hours trying to figure out a) what was going on and b) how to work around it!
-
@FredTingey, happy to be of help, although I cannot claim credit for the discovery of that fix.
-