How to get (childless) “tabs” in a pygtk application - python

I am facing the problem to need tabs in a pygtk app. Pretty much just like gedit has, but without any per-child widget content.
I’ve come across gtk.Notebook, but that requires me to put a widget for each tab, which I don't want.
The reason is, that I have one widget, but would only like to updates its content based on which tab is selected.
Any hints on how to do that?
My idea so far would be to just add some invisible widget for each tab and then connect to the select-page signal. Which widget could I use as invisible widget, or is there a better/alternative way of achieving my goal?

The invisble widget idea works. But not with gtk.Invisible (this just crashes), but with gtk.HBox() or any other thing that seems empty.
self.notebook.append_page(gtk.HBox(), gtk.Label("title"))
Now if I want to display stuff inside the tab actually, I can use reparent to move the widget to the current tab like this.
class Tab(gtk.HBox):
def __init__(self, child):
self.child = child
self.notebook.append_page(Tab(myWidget), gtk.Label("title"))
def pageSelected(self, notebook, page, pagenum):
box = notebook.get_nth_page(pagenum)
box.child.reparent(box)

You can have global widgets, one per tab as you want, in order to access them easily when the tab is selected.
self.notebook.append_page(self.rightBox, gtk.Label("Orders"))
Then connect to the "switch page" signal
self.notebook.connect("switch-page", self.pageSelected)
and :
def pageSelected(self, notebook, page, pagenum):
name = notebook.get_tab_label(notebook.get_nth_page(pagenum))
Now you have "name" with the label of the currently selected page. Just test it (if name == "Orders" ...) to interact.
Hope this was of some help !

Related

Work with different tabs, of the Notebook tkinter

I have a question or problem, maybe there is an answer, but I still can't understand. I have an application, which works with several Notebook tabs
When I click on any button, it calls me a function that in turn works with a class where it creates me, the tab and the widgets:
def open_issuesDeviation (self):
global deviation deviation =
Deviation (self.root)
self.book.add (deviation, text = 'Issues DEVIATIONS')
self.book.select (deviation)
deviation.DESVfr1_entModulo.focus ()
There is even great, I do my tasks I can open,. Tabs and work on them:
My problem is that in the menu bar or in the contextual menu of the right click, when hitting search, call a simple function that does:
def search (self, event):
self.DESVfr1_entModulo.focus()
It is to activate the focus in the entry, when opening each tab and doing CTRL F, or searching in the menu, it manages to activate the focus, the problem is when I return to a previous tab, this no longer works for me, and I have seen that It is because perhaps in each tab, it will be created with a different name to the widget:
Tab 1:
.! Deviation.! Labelframe.! Entry
Tab 2:
.! Deviation2.! Labelframe.! Entry
I think I understand that the last tab is always active.
I have seen that there is a lot of talk about link tags, and I think it may be the solution but I don't understand how I can implement it in my case.

How to make Text scroll down automatically whenever text overcomes the visual area?

Let's say I have a text widget called self.txt. I also have a scrollbar, called scroll.
I have configured the scrollbar to work with self.txt, but I need the Text widget to stay scrolled down, whenever text gets added to it.
Is this doable?
I think this should work: every time the text is modified, this should be called:
def modified(self, event):
self.txt.see(END) # tkinter.END if you use namespaces
To catch the modification, use:
self.txt.bind('<<Modified>>', self.modified)

Trying to make a collapsible widget: How to hide/unhide all child widgets?

Im making a simplish widget that can act as a container for other widgets. One of the features of the widget is that you can expand/collapse it by clicking on it. My current method is basically looking up all child widgets of the layout and hiding them. I'm looking for any help on how to handle this properly - my current implementation has at least one serious caveat: that you can't add widgets while it's collapsed (they're added in an 'unhidden' state)
heres the setCollapsed method that is run when the widget is clicked
def collapsed(self):
return self._isCollapsed
def setCollapsed(self, collapseBool):
self._isCollapsed = collapseBool
if self.layout()!=None:
childWidgets = [self.layout().itemAt(i).widget() for i in range(self.layout().count())]
for w in childWidgets:
if isinstance(w,QtGui.QWidget):
w.setHidden(collapseBool)
if collapseBool:
self._cachedMargin = self.layout().margin()
self.layout().setMargin(0)
else:
self.layout().setMargin(self._cachedMargin)
Rather than hiding all child widgets individually, I would just hide a single parent item.

Big number of pushbuttons and smart checking which is checked

I have dialog:
It contains many flat QPushButtons, QTextEdit and another QPushButton. After click on 'Get list' we can see list of checked buttons in QTextEdit.
My question is how to get this functionality in some smart way. Right now I'm checking every button:
if self.ui.bq6o.isChecked():
cards.append("Q6o")
if self.ui.bk2o.isChecked():
cards.append("K2o")
if self.ui.bq3o.isChecked():
cards.append("Q3o")
if self.ui.bt7s.isChecked():
cards.append("T7s")
if self.ui.bq4o.isChecked():
cards.append("Q4o")
if self.ui.bt4s.isChecked():
cards.append("T4s")
if self.ui.b98o.isChecked():
cards.append("98o")
if self.ui.bjto.isChecked():
cards.append("JTo")
if self.ui.btt.isChecked():
cards.append("TT")
if self.ui.bq7o.isChecked():
cards.append("Q7o")
[...]
Obviously I can't like code like that. I was looking for some widget "button matrix" like, but without luck. I will be grateful for advises.
All the buttons should be children of the same widget, probably the dialog itself. Just get a handle to that widget to get all the child buttons, then loop through them and if they're checked, included their text.
parent = dialog # or whatever
cards = [widget.text() for widget in parent.children() if isinstance(widget, QPushButton) and widget.isChecked()]
You may need to include some code in the if statement to exclude the "Get List" button, or any other pushbuttons in your dialog that could be set to "checked" but shouldn't be included in cards list.
As #Brendan suggested in the other question, you could loop through them in a single list comprehension. But one other approach is to connect each buttons toggled signal to a slot that allows them to register when they are checked.
# somewhere in your class
self.checkedList = set()
def buttonChecked(self, checked):
button = self.sender()
if checked:
self.checkedList.add(button)
else:
if button in self.checkedList:
self.checkedList.remove(button)
# when you create a new button
button.toggled.connect(self.buttonChecked)
This would let you always have a set of just the checked buttons, which are self reporting. Otherwise, you would have to track them under their parent and loop to find out which are checked each time.
Update
Here is a another version that combines #Brendans loop and my signal suggestion. This might help in a situation where your buttons are a bit more spread out across your UI as opposed to be all under a single parent... but first assuming them all under a parent...
parent = dialog
for widget in parent.children():
if isinstance(widget, QPushButton):
widget.toggled.connect(self.buttonChecked)
You could repeat this in your __init__() for all the locations of your buttons and get them all registered to the slot.

How to tweak my tooltips in wxpython?

I was trying to add a tooltip to show the full content of a truncated ObjectListView, until it turned out it had such a feature built-in:
I tried making my own tool tips using wx.TipWindow, wx.PopupWindow and SuperToolTip, but none of them looked as 'native' as this one.
While I'm aware of this wiki article that supposedly enables the tooltip for truncated wx.Listrctrls, I didn't really understand how to get it working. I also expect that it only works when something is truncated, whereas I'd like to be able to use it to display some more information.
I guess the SuperToolTip comes close, but when you remove the 'header' it leaves it with empty space at the top, rather than centering the text in the middle of the tooltip and making it fit.
I tried looking through the source code of ObjectListView, SuperToolTip and wxpython to try and find how tooltips are being created, but I can't really find the low level parts that make it happen.
So how can I tweak tooltips so they look more like native tooltips?
The code to generate my current popups was:
text = "I'm a popup"
class PopUp(wx.TipWindow):
def __init__(self, parent, text):
wx.TipWindow.__init__(self, parent, text)
class PopUp2(wx.PopupWindow):
def __init__(self, parent, text):
wx.PopupWindow.__init__(self, parent)
st = wx.StaticText(self, parent, text)
# Import `from agw import supertooltip as STT`
popup3 = STT.SuperToolTip(text)
I'm not sure if we have a way to create a native Win7 tooltip yet, as you've seen wx.TipWindow looks like the tooltips from older versions of Windows, so there are probably some newer APIs that we should be using instead. Please create a ticket at trac.wxwidgets.org to find out for sure or to request the change if it's not possible some other way that I'm not thinking of at the moment.
Even if you can't create and pop up a native tooltip from scratch, you can still assign the entire ListCtrl a tooltip when you create it, and then change the text to whatever you want based on the item under the mouse pointer. It doesn't position the tooltip neatly over the list item like ObjectListView does, but I think it still accomplishes what you're asking.
self.lc = wx.ListCtrl(self, style=wx.LC_REPORT)
# ...
self.lc.Bind(wx.EVT_MOTION, self.OnMouseMotion)
def OnMouseMotion(self, evt):
pos = self.lc.ScreenToClient(wx.GetMousePosition())
item_index, flag = self.lc.HitTest(pos)
tip = self.lc.GetToolTip()
if flag == wx.LIST_HITTEST_ONITEMLABEL:
tip.SetTip('Some information about ' + self.lc.GetItemText(item_index))
else:
tip.SetTip('')
evt.Skip()

Categories