wx.webkit -- how to get current URL...? - browser

I am trying to build a custom browser using wx.webkit. The following code works cleanly.
I want to get the current URL of the page that is being currently displayed. Using the GetPageURL() method does not seem to help. This always displays the starting URL (http://www.google.com in this case). It does not seem to get updated.
How can i get the updated URL when i navigate from one page to another...?
import wx
import wx.webkit
class wxBrowser(wx.Frame):
def __init__(self, parent, id, title):
wx.Frame.__init__(self, parent, id, title, size=(800, 625))
self.browser = wx.webkit.WebKitCtrl(self,-1)
self.browser.LoadURL('http://www.google.com')
self.browser.Bind(wx.EVT_KEY_DOWN, self.PrintURL)
self.Centre()
self.Show(True)
def PrintURL(self, event):
# show current URL on Cmd P
if event.CmdDown() and event.GetKeyCode() == 80:
print self.browser.GetPageURL()
if __name__ == '__main__':
app = wx.App()
wxBrowser(None, -1, 'My Browser')
app.MainLoop()

Use a wx.html2.WebView.New widget instead.

There is a get_uri() method. You have to use it like this
browser = webkit.WebView()
browser.open("http://example.com")
print browser.get_main_frame().get_uri()

Related

Text of label in UI file can't be changed

I tried it.
from PySide2 import QtWidgets
from PySide2 import QtGui
from PySide2 import QtCore
from PySide2.QtUiTools import QUiLoader
from maya.app.general.mayaMixin import MayaQWidgetBaseMixin
import shiboken2 as shiboken
import os
UIFILEPATH = 'D:/MAYA/pyside_pick/ui/PicsTest5.ui'
class MainWindow(MayaQWidgetBaseMixin,QtWidgets.QMainWindow):
def __init__(self,parent=None):
super(MainWindow,self).__init__(parent)
self.UI = QUiLoader().load(UIFILEPATH)
self.setWindowTitle(self.UI.windowTitle())
self.setCentralWidget(self.UI)
#image
img = QtGui.QPixmap('D:/MAYA/pyside_pick/images/imgKohaku.png')
self.scene = QtWidgets.QGraphicsScene(self)
item = QtWidgets.QGraphicsPixmapItem(img)
self.scene.addItem(item)
self.UI.graphicsView_char_1.setScene(self.scene)
#filter
self._filter = Filter()
self.installEventFilter(self._filter)
self.UI.pSphere1.installEventFilter(self._filter)
#primary
self.UI.label.setStyleSheet("QLabel {color : white;}")
self.UI.label.setText("A")
def labelTest(self):
self.UI.label.setStyleSheet("QLabel {color : red;}")
self.UI.label.setText("B")
print('D')
return False
class Filter(QtCore.QObject):
def eventFilter(self, widget, event):
win = MainWindow()
if event.type() == QtCore.QEvent.MouseButtonPress:
print(widget.objectName())
cmds.select(widget.objectName())
win.labelTest()
return False
def main():
win = MainWindow()
win.show()
if __name__ == '__main__':
main()
I clicked the button that 'pSphere1', but
self.UI.label.setStyleSheet("QLabel {color : red;}") self.UI.label.setText("B")
were look like it's not working.
I can change it inside define with UI loaded, but can't I do setText from outside?
How can I change the label of an imported UI file?
I find this, but I really do not understand. I couldn't find any mention of them beyond this page.
Change comboBox values in Qt .ui file with PySide2
If you know, I also want you to tell me where to put them.
Your issue is within the eventFilter(), and specifically the first line:
win = MainWindow()
This will create a new main window instance, which clearly doesn't make sense, since you obviously want to interact with the existing one.
While you could add the instance as an argument in the filter constructor in order to get a reference to the instance and directly call the function, that wouldn't be very good from the OOP point of view, as objects should never directly access attributes of their "parents".
A better and more correct approach would be to use a custom signal instead, and connect it from the main window instance:
class Filter(QtCore.QObject):
testSignal = QtCore.Signal()
def eventFilter(self, widget, event):
if event.type() == QtCore.QEvent.MouseButtonPress:
print(widget.objectName())
cmds.select(widget.objectName())
self.testSignal.emit()
return False
class MainWindow(MayaQWidgetBaseMixin, QtWidgets.QMainWindow):
def __init__(self, parent=None):
# ...
self._filter.testSignal.connect(self.labelTest)
Note that widgets could accept events and prevent propagation (for instance, buttons or graphics views that have selectable or movable items), so you might not receive the event in the filter in those cases.

What is the right way to create multiple wx.AcceleratorEntry() entries and bind functions to them? wxPython

currently I'm working on my wxPython final High school project and I am facing another problem
I would like to bind keystroke combination entries (for example CTRL+S...) to my functions, but I can not achieve the result that would fulfill my expectations.
I've tried this, but the keystrokes were not bound.
accelnum = 2
accelerators = [wx.AcceleratorEntry() for x in range(accelnum)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), 'save')
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), 'export')
accel=wx.AcceleratorTable(accelerators)
self.SetAcceleratorTable(accel)
def save(self, event):
# some code...
def export(self, event):
# some other code...
I also tried to set ID to the same ID like i set to my toolbar tools but it says
that 'id' is not valid argument here.
Thank you very much for for all the advices. R
EDIT
For all wondering what could be wrong, I also used wx.EVT_CHAR_HOOK to detect "DEL" key. When I was rewriting my class second time, I forgot to add EVT_CHAR_HOOK and it worked. Until I added that EVT_CHAR_HOOK back. That means You can not use it simultaneously. So what I did next:
ID_SAVE = wx.NewIdRef()
ID_EXPORT = wx.NewIdRef()
ID_DELETE = wx.NewIdRef()
accelerators = [wx.AcceleratorEntry() for x in range(3)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), ID_EXPORT)
accelerators[2].Set(wx.ACCEL_NORMAL, wx.WXK_DELETE, ID_DELETE)
to assign also my delete button and it works now
See: https://docs.wxpython.org/wx.AcceleratorEntry.html#wx.AcceleratorEntry.Set
The 3rd parameter to Set is should be the ID to be used when the event is created and sent. So you'll want to do it something like this instead:
ID_SAVE = wx.NewIdRef()
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
When that key is pressed then an EVT_MENU event is sent, so you'll also need to bind a handler for it, like this:
self.Bind(wx.EVT_MENU, self.save, id=ID_SAVE)
Robin's answer, as always, does indeed work.
You may wish to check, exactly how you are implementing it.
Try something like this:
import wx
ID_SAVE = wx.NewIdRef()
ID_EXPORT = wx.NewIdRef()
accelerators = [wx.AcceleratorEntry() for x in range(2)]
accelerators[0].Set(wx.ACCEL_CTRL, ord('S'), ID_SAVE)
accelerators[1].Set(wx.ACCEL_CTRL, ord('E'), ID_EXPORT)
class MyFrame(wx.Frame):
def __init__(self, parent, id=wx.ID_ANY, title="", size=(360,100)):
super(MyFrame, self).__init__(parent, id, title, size)
accel=wx.AcceleratorTable(accelerators)
self.SetAcceleratorTable(accel)
self.panel = wx.Panel(self)
self.Bind(wx.EVT_MENU, self.OnSave, id=ID_SAVE)
self.Bind(wx.EVT_MENU, self.OnExport, id=ID_EXPORT)
self.Show()
def OnSave(self, event):
print("Save")
event.Skip()
def OnExport(self, event):
print("Export")
event.Skip()
if __name__ == "__main__":
app = wx.App()
frame = MyFrame(None,title="An Accelerator Test")
app.MainLoop()
The other answers already explain the 'how to'. Maybe this example can make coding somewhat easier for new readers.
As you can read in the other answers creating an accelerator needs 3 steps: 1) create an id, 2) create an accelerator and 3) bind to EVT_MENU. It took me some time to get it working myself.
So after 'getting the right way' I created a way to make it easier for me, "the easier way", when using a lot of accelerators by defining them in one place.
self._accelerators = {
wx.NewIdRef(): {'text': 'Previous Page (PageUp)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEUP,
'handler': self.on_previous},
wx.NewIdRef(): {'text': 'Next Page (PageDown)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEDOWN,
'handler': self.on_next},
wx.NewIdRef(): {'text': 'Select All (Ctrl+A)',
'flags': wx.ACCEL_CTRL,
'keyCode': ord('a'),
'handler': self.on_select_all},
}
And then let python do the boring stuff.
# ------------------------------------------------------------------------------------------------------------------
def _create_accelerators(self):
entries = []
for event_id, accelerator in self._accelerators.items():
# create the accelerator ---------------------------------------------
entry = wx.AcceleratorEntry(accelerator['flags'], accelerator['keyCode'], event_id)
entries.append(entry)
# bind handler to EVT_MENU ----------------------------------------
self.Bind(wx.EVT_MENU, accelerator['handler'], id=event_id)
accel_tbl = wx.AcceleratorTable(entries)
self.SetAcceleratorTable(accel_tbl)
A complete working example.
import wx
class MyForm(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, title="Accelerator Test", size=(500, 500))
panel = wx.Panel(self, wx.ID_ANY)
# define the accelerators ---------------------------------------------
self._accelerators = {
wx.NewIdRef(): {'text': 'Previous Page (PageUp)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEUP,
'handler': self.on_previous},
wx.NewIdRef(): {'text': 'Next Page (PageDown)',
'flags': wx.ACCEL_NORMAL,
'keyCode': wx.WXK_PAGEDOWN,
'handler': self.on_next},
wx.NewIdRef(): {'text': 'Select All (Ctrl+A)',
'flags': wx.ACCEL_CTRL,
'keyCode': ord('a'),
'handler': self.on_select_all},
}
# create the accelerators ---------------------------
self._create_accelerators()
# ----------------------------------------------------------------------
def _create_accelerators(self):
entries = []
for event_id, accelerator in self._accelerators.items():
# create the accelerator ---------------------------------------------
entry = wx.AcceleratorEntry(accelerator['flags'], accelerator['keyCode'], event_id)
entries.append(entry)
# bind handler to EVT_MENU ----------------------------------------
self.Bind(wx.EVT_MENU, accelerator['handler'], id=event_id)
accel_tbl = wx.AcceleratorTable(entries)
self.SetAcceleratorTable(accel_tbl)
# -------------------------------------------------------------------------------
def on_previous(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# -------------------------------------------------------------------------------
def on_next(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# -------------------------------------------------------------------------------
def on_select_all(self, event):
print(f"You pressed {self._accelerators[event.GetId()]['text']}")
# ===================================================================================
if __name__ == "__main__":
app = wx.App(False)
frame = MyForm()
frame.Show()
app.MainLoop()
Some output.
You pressed Next Page (PageDown)
You pressed Previous Page (PageUp)
You pressed Select All (Ctrl+A)

Retrive date from DateTimeCtrl WXPython

Hey all im having a difficult time with something I believe should be rather simple. Im using WXpython(3.X) to make my GUI and i'm using DatePickerCtrl to form my control. All im trying to do is retrieve the value when I change it. I used the GetValue() method but that only returns the date that currently shows not the one that I changed it to. Then I tried using DateEvent.GetDate but I keep getting an error.
def getStartDate(self):
a = wx.adv.DateEvent(self, self.date_Begin.GetValue(), Event.SetTimestamp()).GetDate
print(a)
return a
and the error that shows up is
**Event.SetTimestamp(): first argument of unbound method must have type 'Event'**
You have declared def getStartDate(self): rather than def getStartDate(self,event):, so you aren't allowing for the event sent to the function.
There is only one event emitted by this function EVT_DATE_CHANGED.
import wx
import datetime
import wx.adv
#----------------------------------------------------------------------
class TestPanel(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None)
sizer = wx.BoxSizer(wx.VERTICAL)
self.SetSizer(sizer)
dpc1 = wx.adv.DatePickerCtrl( self, wx.ID_ANY, wx.DefaultDateTime)
self.Bind(wx.adv.EVT_DATE_CHANGED, self.OnDateChanged, dpc1)
sizer.Add(dpc1, 0, wx.ALL, 50)
# In some cases the widget used above will be a native date
# picker, so show the generic one too.
dpc2 = wx.adv.GenericDatePickerCtrl(self, size=(120,-1),
style = wx.TAB_TRAVERSAL
| wx.adv.DP_DROPDOWN
| wx.adv.DP_SHOWCENTURY
| wx.adv.DP_ALLOWNONE )
self.Bind(wx.adv.EVT_DATE_CHANGED, self.OnDateChanged, dpc2)
sizer.Add(dpc2, 0, wx.LEFT, 50)
now = wx.DateTime.Now()
print (wx.DateTime.FormatISODate(now))
print (wx.DateTime.Format(now))
dpc2.SetValue(wx.DateTime.Now())
def OnDateChanged(self, evt):
sel_date = evt.GetDate()
print (sel_date.Format("%d-%m-%Y"))
#----------------------------------------------------------------------
if __name__ == '__main__':
app = wx.App()
frame = TestPanel()
frame.Show()
app.MainLoop()
Above I reformat the date to dd/mm/yyyy, as I am not from the USA.
If you want more control use wx.adv.CalendarCtrl
You should be able to bind your DatePickerCtrl widget to wx.adv.EVT_DATE_CHANGED
Then in your event handler, you would do something like this:
def OnDateChanged(self, evt):
new_date = evt.GetDate()
print(new_date)
return new_date
Check out the wxPython demo as it has a good example of this widget as well as most of the others.

wx.DirDialog not closing

Using wxPython version 4.0.1 (pheonix) with python 3.6.5
I use a wxPython DirDialog to allow my user to input a start directory. It correctly selects and populates my "working directory" variable (using GetPath()) but then doesn't ever close the directory dialog prompt box.
I read through the wxPython-user google pages and the only related question I found referred to this as being "intended behavior," implying it would happen later in execution (https://groups.google.com/forum/#!searchin/wxpython-users/close%7Csort:date/wxpython-users/ysEZK5PVBN4/ieLGEWc6AQAJ).
Mine, however, doesn't close until the entire script has completed running (which takes a fair amount of time), giving me the spinning wheel of death. I have tried a combination of calls to try to force the window to close.
app = wx.App()
openFileDialog = wx.DirDialog(None, "Select", curr, wx.DD_DIR_MUST_EXIST)
openFileDialog.ShowModal()
working_directory = openFileDialog.GetPath()
openFileDialog.EndModal(wx.CANCEL) #also wx.Close(True) and wx.Destroy()
openFileDialog.Destroy()
openFileDialog=None
I have also tried creating a window, passing it as the parent of the DirDialog, and then closing the window and it gives the same behavior.
You don't mention which operating system you are on or version of wx but in the partial code that you supplied there is no MainLoop, which is what was mentioned by Robin Dunn in his answer, in your link.
Try this and see if it works the way you would expect.
import wx
from os.path import expanduser
import time
class choose(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent, -1, "Dialog")
panel = wx.Panel(self,-1)
text = wx.StaticText(panel,-1, "Place holder for chosen directory")
self.Bind(wx.EVT_CLOSE, self.OnClose)
self.Show()
curr = expanduser("~")
dlg = wx.DirDialog(None, message="Choose a directory", defaultPath = curr,
style=wx.DD_DEFAULT_STYLE|wx.DD_DIR_MUST_EXIST)
if dlg.ShowModal() == wx.ID_OK:
text.SetLabel(dlg.GetPath())
dlg.Destroy()
b = wx.BusyInfo("I'm busy counting",parent=None)
wx.Yield()
for i in range(30):
time.sleep(1)
del b
def OnClose(self, event):
self.Destroy()
if __name__ == '__main__':
my_app = wx.App()
choose(None)
my_app.MainLoop()

Getting changed data from PyQt5 QDialog

I've got a configuration dialog that I'm pre-populating with the existing options, which are stored in cfg. When the user clicks "Save" (or equivalent), I need to get the new values from the QLineEdit objects. Except I can't figure that bit out. I've been Googling and testing since yesterday evening, before I came here on bended knee yet again. Here's my dialog code (the form is from Qt Designer, which is why there's no GUI code):
class Config(QDialog):
def __init__(self):
super(Config, self).__init__()
popup = QDialog()
config_ui = configform()
config_ui.setupUi(popup)
config_ui.programver.setText(cfg['config']['programver'])
if cfg['config']['dummycopy']:
config_ui.democheck.setChecked(True)
config_ui.tmdbAPIkey.setText(cfg['config']['TMDB_KEY'])
config_ui.tvdbAPIkey.setText(cfg['config']['TVDB_KEY'])
config_ui.tvdbUserkey.setText(cfg['config']['TVDB_USERKEY'])
theme = cfg['config']['theme']
if theme == "blue":
config_ui.bluebutton.setChecked(True)
elif theme == "yellow":
config_ui.yellowbutton.setChecked(True)
elif theme == "light":
config_ui.lightmetalbutton.setChecked(True)
elif theme == "dark":
config_ui.darkmetalbutton.setChecked(True)
programversion = config_ui.programver.text()
config_ui.savebutton.clicked.connect(lambda: Config.save(self, programversion))
popup.exec_()
def save(self, programversion):
QDialog.close(self)
print(programversion)
I need some voodoo to get at the changed fields. All I can get now are the original values from when the dialog was brought to life. Is there a trick to this? I can't be the first person to try pre-populating a dialog box. I swear I've tried every combination of button and buttonBox variations available.
I'm thinking maybe there's some way of hiding the dialog, grabbing the data, and then destroying the dialog? That's one working theory, anyway.
Thanks in advance.
To work in a simple way we use the design of Qt Designer to fill the Dialog, and we connect the cancel button to self.reject () and the save button to the save () slot, in this we save the data and issue self.accept () :
from PyQt5.QtWidgets import *
from Ui_config_dialog import Ui_configdialog
import configparser
class Config(QDialog, Ui_configdialog):
def __init__(self, *args, **kwargs):
QDialog.__init__(self, *args, **kwargs)
self.setupUi(self)
self.cancelbutton.clicked.connect(self.reject)
self.filename = "joe.conf"
self.cfg = configparser.ConfigParser()
self.cfg.read(self.filename)
self.load()
def load(self):
self.programver.setText(self.cfg['config']['programver'])
self.democheck.setChecked(self.cfg.getboolean("config", "dummycopy"))
self.tmdbAPIkey.setText(self.cfg['config']['TMDB_KEY'])
self.tvdbAPIkey.setText(self.cfg['config']['TVDB_KEY'])
self.tvdbUserkey.setText(self.cfg['config']['TVDB_USERKEY'])
theme = self.cfg['config']['theme']
self.buttons = {"blue": self.bluebutton,
"yellow": self.yellowbutton,
"light": self.lightmetalbutton,
"dark": self.darkmetalbutton}
self.buttons[theme].setChecked(True)
self.group = QButtonGroup(self)
self.group.addButton(self.bluebutton)
self.group.addButton(self.yellowbutton)
self.group.addButton(self.lightmetalbutton)
self.group.addButton(self.darkmetalbutton)
self.savebutton.clicked.connect(self.save)
def save(self):
self.cfg['config']['programver'] = self.programver.text()
self.cfg['config']['dummycopy'] = "True" if self.democheck.isChecked() else "False"
self.cfg['config']['TMDB_KEY'] = self.tmdbAPIkey.text()
self.cfg['config']['TVDB_KEY'] = self.tvdbUserkey.text()
for key, btn in self.buttons.items():
if btn == self.group.checkedButton():
self.cfg['config']['theme'] = key
break
with open(self.filename, 'w') as configfile:
self.cfg.write(configfile)
self.accept()
if __name__ == "__main__":
import sys
app = QApplication(sys.argv)
w = Config()
w.show()
sys.exit(app.exec_())

Resources