wxPython: Disable a notebook tab? - python

Is there anyway to disable a notebook tab? Like you can with the Widgets themselves? I have a long process I kick off, and while it should be pretty self-explanatory for those looking at it, I want to be able to prevent the user from mucking around in other tabs until the process it is running is complete.
I couldn't seem to find anything in wx.Notebook to help with this?
Code snippet:
def __init__(self, parent):
wx.Notebook.__init__(self, parent, id=wx.ID_ANY, style=wx.BK_DEFAULT)
self.AddPage(launchTab.LaunchPanel(self), "Launch")
self.AddPage(scanTab.ScanPanel(self), "Scan")
self.AddPage(extractTab.ExtractPanel(self), "Extract")
self.AddPage(virtualsTab.VirtualsPanel(self), "Virtuals")

It si not doable with wx.Notebook. But you can use some of the more advanced widgets such as wx.lib.agw.aui.AuiNotebook:
import wx
import wx.lib.agw.aui as aui
class MainWindow(wx.Frame):
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, *args, **kwargs)
style = aui.AUI_NB_DEFAULT_STYLE ^ aui.AUI_NB_CLOSE_ON_ACTIVE_TAB
self.notebook = aui.AuiNotebook(self, agwStyle=style)
self.panel1 = wx.Panel(self.notebook)
self.panel2 = wx.Panel(self.notebook)
self.panel3 = wx.Panel(self.notebook)
self.notebook.AddPage(self.panel1, "First")
self.notebook.AddPage(self.panel2, "Second")
self.notebook.AddPage(self.panel3, "Third")
self.notebook.EnableTab(1, False)
self.Show()
app = wx.App(False)
win = MainWindow(None)
app.MainLoop()

Technically, wx.Notebook doesn't have a way to disable a tab. However, you can do the same thing by checking which tab is clicked on and if it is "disabled", veto the EVT_NOTEBOOK_PAGE_CHANGING or EVT_NOTEBOOK_PAGE_CHANGED event. Alternately, you can use the AUI notebook as mentioned above. Note that that is the one from the agw lib, NOT from the wx.aui one. The FlatNotebook also provides the ability to disable tabs. See the wxPython demo for an example.

class MainFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None)
p = wx.Panel(self)
self.nb = wx.Notebook(p)
......
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
def OnPageChanged(self, event):
if wx.IsBusy():
self.Unbind(wx.EVT_NOTEBOOK_PAGE_CHANGED)
self.nb.SetSelection(event.GetOldSelection())
self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged)
The active tab can be set by Notebook.SetSelection(). But the event should be unbinded/disable and bind/enable around it to avoid in infinite looping. There should be wx.BeginBusyCursor(), wx.EndBusyCursor() in panel codes. Then The tab changing is "disabled" when app is busy.

Related

Disable windows border with wxpython and cefpython3

I am following this example https://github.com/cztomczak/cefpython/blob/master/examples/wxpython.py for cefpython3 and wxpython. However I am looking to disable the windows border so the program can no longer be adjusted size wise and their is no title bar. But I would like to keep it so the program can be moved around the screen. I have done some research but not come across a way to successfully do this.
The following appears to do the job on Linux.
Your mileage may vary.
import wx
class MyFrame(wx.Frame):
def __init__(self, parent, id=wx.ID_ANY, title="", size=(360,100)):
super(MyFrame, self).__init__(parent, id, title, size, style = wx.DEFAULT_FRAME_STYLE & ~(wx.RESIZE_BORDER | wx.MAXIMIZE_BOX))
self.panel = wx.Panel(self)
self.panel.SetBackgroundColour('palegreen')
self.Show()
if __name__ == "__main__":
app = wx.App()
frame = MyFrame(None,title="Non-Resizeable Frame")
app.MainLoop()

ESC key in wx.Dialog doesn't trigger button with ID_CANCEL unless it has focus

According to the docs, dialogs created in wxPython and shown with ShowModal should handle the escape (ESC) key by searching for a button with ID_CANCEL and simulating a click (i.e. triggering its EVT_BUTTON event).
This was working in all but one of my dialogs. After a lot of debugging, I discovered that the cancel button - or any other button! - should have focus. In other words, as long as I call .SetFocus() on one of the buttons I create, the ESC key works fine.
Does anybody know what's going on here? Do dialogs displayed with ShowModal() not automatically get focus? Should they? Or am I misunderstanding something?
In the example code below, uncomment the line b.SetFocus() to see the difference:
import wx
class MainWindow(wx.Frame):
def __init__(self, parent):
super(MainWindow, self).__init__(parent)
self.Show()
d = SomeDialog(self)
d.ShowModal()
self.Destroy()
class SomeDialog(wx.Dialog):
def __init__(self, parent):
super(SomeDialog, self).__init__(parent)
button = wx.Button(self, wx.ID_CANCEL, 'Cancel')
button.Bind(wx.EVT_BUTTON, self.action_cancel)
#button.SetFocus()
def action_cancel(self, e):
self.EndModal(wx.ID_CANCEL)
if __name__ == '__main__':
app = wx.App(False)
frame = MainWindow(None)
app.MainLoop()
Update: This happens when running on linux (Fedora 20, Gnome)
You can call the dialog's SetFocus() method to set focus on itself:
import wx
class MainWindow(wx.Frame):
def __init__(self, parent):
super(MainWindow, self).__init__(parent)
self.Show()
d = SomeDialog(self)
d.ShowModal()
self.Destroy()
class SomeDialog(wx.Dialog):
def __init__(self, parent):
super(SomeDialog, self).__init__(parent)
button = wx.Button(self, wx.ID_CANCEL, 'Cancel')
button.Bind(wx.EVT_BUTTON, self.action_cancel)
self.SetFocus()
def action_cancel(self, e):
self.EndModal(wx.ID_CANCEL)
if __name__ == '__main__':
app = wx.App(False)
frame = MainWindow(None)
app.MainLoop()
This works on Kubuntu 14.04 with wxPython 2.8.12.1 and Python 2.7.6. However, I suspect that when you set focus to the dialog, it is probably passing the focus to its first child just as a wx.Panel will do. I don't know why Linux is behaving in this manner, but I would agree with #nepix32 and #VZ that this should work without the SetFocus(). You can call it anyway as a workaround, but you should probably report it as a bug. There's a link on the wxPython website where you can submit your bug report.

Good way of implementing more windows in PyQt

How to open a new window after the user clicks a button is described here:
https://stackoverflow.com/a/21414775/1898982
and here:
https://stackoverflow.com/a/13519181/1898982
class Form1(QtGui.QWidget, Ui_Form1):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
self.button1.clicked.connect(self.handleButton)
self.window2 = None
def handleButton(self):
if self.window2 is None:
self.window2 = Form2(self)
self.window2.show()
class Form2(QtGui.QWidget, Ui_Form2):
def __init__(self, parent=None):
QtGui.QWidget.__init__(self, parent)
self.setupUi(self)
I want to develop a GUI application that consists of several steps. Once the user clicks next, the current window closes and another window opens. Technically I can do this like it is described above: Each window opens a new one. After a few steps this is pretty much nested.
Is there a better way to do this?
I would like to have the control flow in my main. Something like this:
main()
window1 = win2()
window1.show()
wait until button in window1 is clicked, then
window1.close()
window2 = win2()
window2.show()
wait until button in window2 is clicked, then
window1.close()
....
I would recommend to use QWizard or QStackedWidget class to perform this task. You can easily switch between widgets or windows using either of these two classes. Refer to QWizard and QStackedWidget docs.
Qt provides special widget for such cases, which called QWidget. Look at it. It's also available in Qt4.

Using wx.lib.agw.artmanager, ArtManager().DropShadow()

On Windows 7 64-bit, using Python 2.7.3 and wx version 2.8.12.1.
I'm trying to get a wx.Frame styled as wx.SIMPLE_BORDER or wx.NO_BORDER to have a shadow like other windows, like this:
Drop Shadow
Unfortunately, this seems to be a part of the wx.RESIZE_BORDER style. Here is what happens without that:
No Shadow
So, I went to Googling and found this ArtManager class in the wx.lib.agw.artmanager module, which had a DropShadow function, claiming that it "Adds a shadow under the window (Windows Only)."
But, it didn't seem to do anything. No errors, but no results. Perhaps it doesn't work on Windows 7, but I'm hoping you have a better answer. Of course, I'd be open to other methods of creating a shadow, but this is the one I had found.
Here's my code:
import wx
import wx.lib.agw.artmanager
class main(wx.Frame):
def __init__(self, parent, id):
wx.Frame.__init__(self, parent, id, style=wx.SIMPLE_BORDER, size=(469, 400))
am = wx.lib.agw.artmanager.ArtManager()
self.Center()
self.Show()
am.DropShadow(self, True)
class app(wx.App):
def OnInit(self):
frame = main(None, -1)
frame.Show(True)
return True
app = app()
app.MainLoop()

Flatnotebook ignores all styles

In the following sample program I can't seem to get the notebook control to use the styles I tell it to use. Despite the FNB_HIDE_ON_SINGLE_TAB, FNB_NO_NAV_BUTTONS and FNB_X_ON_TABS styles I still see the navigation buttons and a single tab with no close button. It's the same for all styles I've tried, they're all completely ignored.
I'm running this on Ubuntu 11.10, python 2.7.2 and wxPython 2.8.11 if it matters
import wx
import wx.lib.flatnotebook as FNB
class TabCtrl(FNB.FlatNotebook):
def __init__(self, parent):
windowstyle = FNB.FNB_HIDE_ON_SINGLE_TAB|FNB.FNB_NO_NAV_BUTTONS|FNB.FNB_X_ON_TAB
super(TabCtrl, self).__init__(parent, style=windowstyle)
self.pages = []
self.pages.append(wx.Panel(self))
self.AddPage(self.pages[0], 'Test')
class MainFrame(wx.Frame):
def __init__(self, *args, **kwargs):
super(MainFrame, self).__init__(*args, **kwargs)
self.panel = wx.Panel(self)
self.tabs = TabCtrl(self.panel)
sizer = wx.GridBagSizer(vgap=8, hgap=8)
sizer.Add(self.tabs, (0, 0), (10, 30), wx.EXPAND)
sizer.AddGrowableCol(29)
sizer.AddGrowableRow(9)
self.panel.SetSizer(sizer)
self.panel.Fit()
self.SetInitialSize()
class App(wx.App):
def __init__(self, *args, **kwargs):
super(App, self).__init__(*args, **kwargs)
self.frame = MainFrame(None, title='Test')
self.frame.Show()
app = App()
app.MainLoop()
FNB_NO_NAV_BUTTONS and FNB_X_ON_TABS both work on my machine (using the wxPython demo) using wxPython 2.8.12, Windows 7, Python 2.6. When it comes to anything in the AGW widget set, I highly recommend downloading the latest version from SVN. I know the author of that library and he's always updating it and fixing bugs, so updating to the latest in SVN is usually worth it.
EDIT: I was looking at this again and I think you're putting at least some of those flags in on the wrong parameter. There's an "agwStyle" argument in FlatNotebook too and I'm thinking that's where some or all of those FlatNotebook-related flags should be applied to:
super(TabCtrl, self).__init__(parent, agwStyle=windowstyle)
It may be a bug. I have tried various ways to change the style without being successful. Even example located on wxPyWiki does not work for me when it comes to changing the styles.
I would consider asking about it on wxPython-users mailing list.

Categories

Resources