Making tooltip texts on wxpython Ribbon control - user-interface

I'm trying to create tooltip texts for a ribbon control. I have set the help_strings but don't know how to display them. Even if it is just a tooltip text as wxpython displays for a button would be fine for me.
I have attached the code sample (a modified version of the RibbobDemo.py) on which I would like to have the help_strings on mouseover.
I appreciate code examples or pointing references.
import wx
import wx.lib.agw.ribbon as RB
class RibbonFrame(wx.Frame):
def __init__(self, parent, id=wx.ID_ANY, title="", pos=wx.DefaultPosition,
size=wx.DefaultSize, style=wx.DEFAULT_FRAME_STYLE):
wx.Frame.__init__(self, parent, id, title, pos, size, style)
self._ribbon = RB.RibbonBar(self, wx.ID_ANY)
home = RB.RibbonPage(self._ribbon, wx.ID_ANY, "Examples", wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN))
toolbar_panel = RB.RibbonPanel(home, wx.ID_ANY, "Toolbar", wx.NullBitmap, wx.DefaultPosition,
wx.DefaultSize, RB.RIBBON_PANEL_NO_AUTO_MINIMISE)
toolbar = RB.RibbonToolBar(toolbar_panel, wx.ID_ANY)
# this is just a simple tool
toolbar.AddTool(wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_FILE_OPEN), help_string=" the first tool")
toolbar.AddTool(wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_ERROR), help_string=" the second tool")
toolbar.AddTool(wx.ID_ANY, wx.ArtProvider.GetBitmap(wx.ART_INFORMATION), help_string=" the third tool")
toolbar.AddSeparator()
self._ribbon.Realize()
self._logwindow = wx.TextCtrl(self, wx.ID_ANY, "", wx.DefaultPosition, wx.DefaultSize,
wx.TE_MULTILINE | wx.TE_READONLY | wx.TE_LEFT | wx.TE_BESTWRAP | wx.BORDER_NONE)
s = wx.BoxSizer(wx.VERTICAL)
s.Add(self._ribbon, 0, wx.EXPAND)
s.Add(self._logwindow, 1, wx.EXPAND)
self.SetSizer(s)
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = RibbonFrame(None, -1, "wxPython Ribbon Sample Application", size=(800, 600))
frame.CenterOnScreen()
frame.Show()
app.MainLoop()

I got wxPython3.0 Docs and Demos installed from http://www.wxpython.org/download.php. In that, under the Advanced Generic Widgets, I found the demo for Pure-Python RibbonBar which has a tooltip text display. It displays as a usual button tooltip. However, I decided to satisfy myself by that. I thank everyone involved in compiling the docs and demos. It will be very very useful!

Related

Matplotlib embedded in wxPython: TextCtrl in Navigation toolbar not working on macos

I'm doing a simple embedded graph with Matplotlib APIs (2.2.2) in wxPython (Phoenix 4.0.1) and Python 3.6.4. I have subclassed the WXAgg Navigation toolbar so I can remove the "configure subplots" tool and this is working fine.
In addition, I have added a read-only TextCtrl into my subclassed toolbar to show mouse coordinates (just like it appears in the pyplot state-based version of matplotlib). I've implemented a simple handler for the mouse move events per the Matplotlib docs and this is all working fine on Windows 10.
However, this code does not fully work on macOS (10.13.4 High Sierra). The graph displays just fine, the toolbar displays fine, the toolbar buttons work fine, but I don't get any display of my TextCtrl with the mouse coordinates in the toolbar (or even the initial value as set when I create the TextCtrl).
Can anyone shed light on why the TextCtrl in the Matplotlib toolbar doesn't work on the mac? Is there a way to do this on the mac? And if this is simply not possible, what are my alternatives for showing the mouse coordinates elsewhere in my Matplotlib canvas?
Here's my sample code:
import wx
from matplotlib.figure import Figure
from matplotlib import gridspec
import numpy as np
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx as NavigationToolbar
class MyToolbar(NavigationToolbar):
def __init__(self, plotCanvas):
# create the default toolbar
NavigationToolbar.__init__(self, plotCanvas)
# Add a control to display mouse coordinates
self.info = wx.TextCtrl(self, -1, value = 'Coordinates', size = (100,-1),
style = wx.TE_READONLY | wx.BORDER_NONE)
self.AddStretchableSpace()
self.AddControl(self.info)
# Remove configure subplots
SubplotsPosition = 6
self.DeleteToolByPos(SubplotsPosition)
self.Realize()
class Graph(wx.Frame):
def __init__(self, parent, title='Coordinates Test'):
super().__init__(parent, title=title)
self.SetSize((900, 500))
# A simple embedded matplotlib graph
self.fig = Figure(figsize = (8.2,4.2), facecolor = 'gainsboro')
self.canvas = FigureCanvas(self, -1, self.fig)
gs = gridspec.GridSpec(2, 1, left = .12, right = .9, bottom = 0.05, top = .9, height_ratios = [10, 1], hspace = 0.35)
ax = self.fig.add_subplot(gs[0])
t = np.arange(0.0, 2.0, 0.01)
s = 1 + np.sin(2 * np.pi * t)
ax.plot(t, s)
ax.set(xlabel='time (s)', ylabel='voltage (mV)',
title='About as simple as it gets, folks')
ax.grid()
ax.set_navigate(True)
# Get a toolbar instance
self.toolbar = MyToolbar(self.canvas)
self.toolbar.Realize()
# Connect to matplotlib for mouse movement events
self.canvas.mpl_connect('motion_notify_event', self.onMotion)
self.toolbar.update()
# Layout the frame
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.EXPAND)
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
self.SetSizer(self.sizer)
def onMotion(self, event):
if event.inaxes:
xdata = event.xdata
ydata = event.ydata
self.toolbar.info.ChangeValue(f'x = {xdata:.1f}, y = {ydata:.1f}')
else:
self.toolbar.info.ChangeValue('')
class MyFrame(wx.Frame):
def __init__(self, parent, title=""):
super().__init__(parent, title=title)
self.SetSize((800, 480))
self.graph = Graph(self)
self.graph.Show()
class MyApp(wx.App):
def OnInit(self):
self.frame = MyFrame(None, title='Main Frame')
self.frame.Show()
return True
if __name__ == "__main__":
app = MyApp(False)
app.MainLoop()
I realize this is late, but I think that the simplest solution is to not subclass NavigationToolbar at all, but just to add a TextCtrl of your own.
That is, getting rid of your MyToolbar altogether and modifying your code to be
# Get a toolbar instance
self.toolbar = NavigationToolbar(self.canvas)
self.info = wx.TextCtrl(self, -1, value = 'Coordinates', size = (100,-1),
style = wx.TE_READONLY | wx.BORDER_NONE)
self.canvas.mpl_connect('motion_notify_event', self.onMotion)
self.toolbar.update()
# Layout the frame
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.EXPAND)
bottom_sizer = wx.BoxSizer(wx.HORIZONTAL)
bottom_sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
bottom_sizer.Add(self.info, 1, wx.LEFT | wx.EXPAND)
self.sizer.Add(bottom_sizer, 0, wx.LEFT | wx.EXPAND)
self.SetSizer(self.sizer)
def onMotion(self, event):
if event.inaxes is not None:
xdata = event.xdata
ydata = event.ydata
self.info.ChangeValue(f'x = {xdata:.1f}, y = {ydata:.1f}')
else:
self.info.ChangeValue('')
will give TextCtrl that does display the motion events.

Multilpe screen in wxpython

all.
I'd like to be able to switch between multiple screens. Meaning, the first one is the main, then when with a button or an external switch is activated I can see the page #2, in that one I may have an other button to return to the first one, or going to #3, etc. Cause I have a main screen for a big RPM meter, but I may want to see instead all three meter on the same page, or view the raw data in an other page, or go to the set-up page or elsewhere in the future development. I'm using the full screen space for my graphic. Maybe something like "hide" or "show" a page with an event of some kind. I have a single class script for every pages so far, but unable to group them in a single one. Thanks for your help
I wrote about this concept several years ago here. I went ahead an reproduced the example from that article:
import wx
import wx.grid as gridlib
class PanelOne(wx.Panel):
""""""
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
txt = wx.TextCtrl(self)
class PanelTwo(wx.Panel):
""""""
def __init__(self, parent):
"""Constructor"""
wx.Panel.__init__(self, parent=parent)
grid = gridlib.Grid(self)
grid.CreateGrid(25,12)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(grid, 0, wx.EXPAND)
self.SetSizer(sizer)
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY,
"Panel Switcher Tutorial")
self.panel_one = PanelOne(self)
self.panel_two = PanelTwo(self)
self.panel_two.Hide()
self.sizer = wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.panel_one, 1, wx.EXPAND)
self.sizer.Add(self.panel_two, 1, wx.EXPAND)
self.SetSizer(self.sizer)
menubar = wx.MenuBar()
fileMenu = wx.Menu()
switch_panels_menu_item = fileMenu.Append(wx.ID_ANY,
"Switch Panels",
"Some text")
self.Bind(wx.EVT_MENU, self.onSwitchPanels,
switch_panels_menu_item)
menubar.Append(fileMenu, '&File')
self.SetMenuBar(menubar)
def onSwitchPanels(self, event):
""""""
if self.panel_one.IsShown():
self.SetTitle("Panel Two Showing")
self.panel_one.Hide()
self.panel_two.Show()
else:
self.SetTitle("Panel One Showing")
self.panel_one.Show()
self.panel_two.Hide()
self.Layout()
# Run the program
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
The basic idea here is to Hide() one panel and Show() another. You might also want to look at the Notebook controls that wxPython provides as they have a similar functionality.

Toolbar rendering following wxPython 2.9 upgrade

This code worked fine on wxPython 2.8, following an upgrade today to 2.9 however the toolbar doesn't
display at all. If I remove the self.SetToolBar() call the icon does show up but not as a button, and the toolbar formatting doesn't stretch when the screen is re-sized. Any ideas?
import wx
class MyApp(wx.App):
def OnInit(self):
self.frame = Example(None, title="Word Bag", size=(400,100))
self.SetTopWindow(self.frame)
self.frame.Show()
return True
class MyToolbar(wx.ToolBar):
"""Toolbars are attached to frames, so need TBar = Toolbar(self) in frame init"""
def __init__(self, parent):
wx.ToolBar.__init__(self, parent)
# set my preferred default size for icons
self.SetToolBitmapSize((32,32))
# the main bit where icons are formatted, added, and bound to handlers
self.initialiseIcons()
# Need to call realise before exiting
self.Realize()
def initialiseIcons(self):
"""Iterate over icons and add them to toolbar"""
for each in self.toolbarData():
self.createSimpleTool(*each)
def createSimpleTool(self, label, filename, statbar, handler):
"""Adds icons to bar using AddSimpleTool"""
if not label:
self.AddSeparator()
return
bmp = wx.Image(filename, wx.BITMAP_TYPE_PNG).ConvertToBitmap()
tool = self.AddSimpleTool(-1, bmp, label, statbar)
self.Bind(wx.EVT_MENU, handler, tool)
def toolbarData(self):
"""Put your icon data here in the following format...
[0] = tooltip label, [1] = bitmap path, [2] = status bar label, [3] = bound function"""
return [["Add new word","/Users/paulpatterson/Desktop/add.png","Add a new word to the dictionary",self.OnAddWord]]
# toolbar icon handlers here...
def OnAddWord(self, event):
pass
def OnRemoveWord(self, event):
pass
def OnSearchWord(self, event):
pass
class Example(wx.Frame):
def __init__(self, parent, title, size):
super(Example, self).__init__(parent, title=title, size=size)
# Create and set the toolbar
tBar = MyToolbar(self)
self.SetToolBar(tBar)
self.frameSizer = wx.BoxSizer(wx.VERTICAL)
self.panelOne = MyPanel(self)
self.frameSizer.Add(self.panelOne, 1, wx.EXPAND)
self.SetSizer(self.frameSizer)
#self.frameSizer.Fit(self)
self.Centre()
self.Show()
class MyPanel(wx.Panel):
def __init__(self, parent):
super(MyPanel, self).__init__(parent)
self.mainSizer = wx.BoxSizer(wx.VERTICAL)
### widgets here
# set optimum layout for mainsizer...
self.SetSizer(self.mainSizer)
# ...then fit main sizer to the panel.
self.mainSizer.Fit(self)
if __name__ == '__main__':
app = MyApp(False)
app.MainLoop()
I had the same problem just hours ago. I couldn't get a custom created toolbar to work, but using Frame.CreateToolBar() works as expected. Example:
class MyFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(
self, parent=None, id=-1, title='Test window',
size=wx.Size(800, 600)
)
self.setup_toolbar()
def setup_toolbar(self):
# First create the toolbar.
self.toolbar = self.CreateToolBar(wx.TB_FLAT | wx.TB_TEXT)
self.Bind(wx.EVT_TOOL, self.on_toolbar)
# Add a 'Clear all' button.
self.toolbar.AddLabelTool(
wx.ID_NEW, 'Clear all', get_toolbar_art('new_big'),
shortHelp='Remove all the contents from the text inputs.'
)
# Add an 'Open' button.
self.toolbar.AddLabelTool(
wx.ID_OPEN, 'From file...', get_toolbar_art('open_big'),
shortHelp='Fill the input box with the ' +
'contents of a Linjekort text file.'
)
# self.toolbar.AddSeparator() # A separator.
# Add a 'Save all' button.
self.toolbar.AddLabelTool(
wx.ID_SAVE, 'Save results to...', get_toolbar_art('save_big'),
shortHelp='Save all the Ozi files to a directory.'
)
self.toolbar.Realize()
def get_toolbar_art(name):
return wx.Bitmap('icons/{}.png'.format(name))
But this doesn't answer how to get a custom toolbar subclass to work. Have you tried to just add the toolbar to your layout using a sizer, not using the SetToolBar function? That's the only way I know of to avoid ending up with the OSX native Frame toolbar. Here's an example of that done:
def create_output_panel(self, parent, slug, label):
panel = wx.Panel(parent, style=wx.BORDER_THEME)
panel.SetBackgroundColour(
wx.SystemSettings.GetColour(wx.SYS_COLOUR_3DSHADOW)
)
# Toolbar.
toolbar = wx.ToolBar(panel, -1, style=wx.BORDER_RAISED)
toolbar.AddSimpleTool(
wx.ID_SAVE, get_toolbar_art('save'),
shortHelpString='Save to file...'
)
toolbar.Realize()
toolbar.Bind(wx.EVT_TOOL, lambda evt: print('Success'))
# Text control.
textctrl = wx.TextCtrl(
panel, -1, style=wx.TE_READONLY | wx.TE_MULTILINE | wx.BORDER_NONE
)
# Organize controls.
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(
wx.StaticText(panel, -1, label), proportion=0, border=5, flag=wx.ALL
)
sizer.Add(toolbar, proportion=0, flag=wx.EXPAND)
sizer.Add(textctrl, proportion=1, flag=wx.EXPAND)
panel.SetSizer(sizer)
return panel
And a screen shot:
I hope this helps!

Radio buttons using wxpython

I'm Building a gui using wxpython.. i have buttons and radiobuttons in it, and i wanna
to do such tasks based on what the current values of the widgets in the gui .. the insert
button has a multiple if statement one of these if statement is to check whether a
radiobutton is selected. i dont want to bind an event to the radio button so i have
checked about it in the insert button using
this is the defined radion button
self.rb1 = wx.RadioButton(self.panel, -1, 'Is this a required pre_action to the next
step?', (5, 220))
and this is the check condition
if self.rb1.GetValue():
# do something here
and also :
if self.rb1.GetValue() == 'True':
# do some tasks
in both way (which is already the same) the is nothing happend when i choose the radio
button rb1 ! so what is the problwm of this ?
I don't know what that doesn't work for you. It works for me just fine. See sample code below:
import wx
class MyForm(wx.Frame):
#----------------------------------------------------------------------
def __init__(self):
wx.Frame.__init__(self, None, wx.ID_ANY, "Tutorial")
panel = wx.Panel(self, wx.ID_ANY)
self.radio = wx.RadioButton(panel, label="Test", style = wx.RB_GROUP)
self.radio2 = wx.RadioButton(panel, label="Test2")
btn = wx.Button(panel, label="Check Radio")
btn.Bind(wx.EVT_BUTTON, self.onBtn)
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.radio, 0, wx.ALL, 5)
sizer.Add(self.radio2, 0, wx.ALL, 5)
sizer.Add(btn, 0, wx.ALL, 5)
panel.SetSizer(sizer)
#----------------------------------------------------------------------
def onBtn(self, event):
""""""
print "First radioBtn = ", self.radio.GetValue()
print "Second radioBtn = ", self.radio2.GetValue()
# Run the program
if __name__ == "__main__":
app = wx.PySimpleApp()
frame = MyForm().Show()
app.MainLoop()

Scrolling area with PyQT on Maemo5

I'm not really accustomed to writing the UI in the code, so I need a few pointers.
I'm trying to create a simple, horizontal scrolling dialog on my N900, but I can't figure out how to do this.
This is what I have so far:
def __init__(self,parent = None):
QDialog.__init__(self,parent)
#if name == None:
self.setWindowTitle('Testing scrolling')
self.scrollArea = QScrollArea(self)
self.scrollArea.setWidgetResizable(True)
self.scrollArea.setMinimumSize(100,150)
self.aWidget = QWidget(self.scrollArea)
self.aWidget.setMinimumSize(20,200)
self.aWidget.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding)
self.scrollArea.setSizePolicy( QSizePolicy.Expanding, QSizePolicy.Expanding)
self.scrollArea.setWidget(self.aWidget)
scroller = self.scrollArea.property("kineticScroller").toPyObject()
scroller.setEnabled(True)
_layout = QGridLayout(self.aWidget)
_layout.setSpacing(60)
_layout.setMargin(11)
_layout.addWidget(QPushButton('Test0'),0,0)
_layout.addWidget(QPushButton('Test1'),0,1)
_layout.addWidget(QPushButton('Test2'),0,2)
_layout.addWidget(QPushButton('Test3'),0,3)
_layout.addWidget(QPushButton('Test4'),0,4)
_layout.addWidget(QPushButton('Test5'),0,5)
_layout.addWidget(QPushButton('Test6'),0,6)
Pls, check if an example below would help you out, it should create a dialog with horizontal scroll area and buttons in it.
class MyDialog(QDialog):
def __init__(self,parent = None):
QDialog.__init__(self,parent)
self.setWindowTitle('Testing scrolling')
self.setGeometry(250, 200, 350, 400)
widget = QWidget()
widgetLayout = QHBoxLayout()
for i in range(0, 25):
button = QPushButton("test button {0}".format(i))
widgetLayout.addWidget(button)
widget.setLayout(widgetLayout)
scrollArea = QScrollArea()
scrollArea.setWidget(widget)
dialogLayout = QVBoxLayout()
dialogLayout.addWidget(scrollArea)
self.setLayout(dialogLayout)
if __name__ == "__main__":
app = QtGui.QApplication(sys.argv)
dlg = MyDialog()
dlg.show()
sys.exit(app.exec_())
hope this helps, regards

Resources