How get string selection in wx.html.htmlwindow - python

I can not get a method to manage clipboard with the context menu
I'm trying with version 2.8 of wxpython
import wx
import wx.lib.iewin
class main (wx.Frame):
def __init__(self, parent):
wx.Frame.__init__ (self, parent, id, title, pos, size, style)
self.html_field = HTMLWINDOW(self.p_html, -1)
class HTMLWINDOW(wx.html.HtmlWindow):
def __init__(self, parent, id):
self.ie = wx.lib.iewin.IEHtmlWindow(self, -1, style)
self.Bind(wx.EVT_CONTEXT_MENU, self.menu)
def menu(self, event):
self.copied = self.ie.GetStringSelection()
alternative method. but only I can get words, not a whole selection
def OnCellClicked(self, cell, x, y, evt):
if isinstance(cell, wx.html.HtmlWordCell):
sel = wx.html.HtmlSelection()
word = cell.ConvertToText(sel)
super(MyHtmlWindow, self).OnCellClicked(cell, x, y, evt)
importing wx.lib.iewin I get this error
Traceback (most recent call last):
ValueError: _type_ 'v' not supported
File "main.py", line 3959, in <module>
import wx.lib.iewin as iewin
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/iewin.py", line 15, in <module>
import wx.lib.activex
File "/usr/lib/python2.7/dist-packages/wx-2.8-gtk2-unicode/wx/lib/activex.py", line 35, in <module>
import ctypes.wintypes as wt
File "/usr/lib/python2.7/ctypes/wintypes.py", line 23, in <module>
class VARIANT_BOOL(_SimpleCData):
ValueError: _type_ 'v' not supported

As Werner already pointed out, you are attempting to import wx.lib.iewin in Linux. The iewin module is Windows only. I think it should give an import error that tells you it's Windows only, but the name itself implies that. You could put in a bug ticket so that it does raise an appropriate error though.
If you need a browser-like widget, then you should check out WebView. It was added in wxPython 2.9, I believe and works cross-platform. You can read more about that widget here:
https://wxpython.org/Phoenix/docs/html/wx.html2.WebView.html

Related

Why is Label object not callable appearing

I am in the process of making an OOP Countdown GUI with the letters, numbers and conundrum games.
This is a snippet of my code so far.
class App(tk.Tk):
def __init__(self):
super().__init__()
self.title("Main")
self.configure(bg=LIGHT_BLUE)
self.title=tk.Label(master=self,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="!Countdown Games!",pady=5,padx=5)
self.title.pack()
self.frame=tk.Frame(master=self,bg=LIGHT_BLUE)
self.LettersButton=tk.Button(master=self.frame,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="Letters",command=self.start_letters)
self.LettersButton.grid(row=0,column=0,sticky="NESW",pady=10,padx=2)
self.NumbersButton=tk.Button(master=self.frame,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="Numbers",command=self.start_numbers)
self.NumbersButton.grid(row=0,column=1,sticky="NESW",pady=10,padx=2)
self.LettersButton=tk.Button(master=self.frame,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="Conundrum",command=self.start_conundrum)
self.LettersButton.grid(row=0,column=2,sticky="NESW",pady=10,padx=2)
self.frame.pack()
self.mainloop()
def start_letters(self):
self.withdraw()
self.Letters=Letters()
def start_numbers(self):
self.withdraw()
self.Numbers=Numbers()
def start_conundrum(self):
self.withdraw()
self.Conundrum=Conundrum()
class Conundrum(tk.Toplevel):
def __init__(self):
super().__init__()
self.configure(bg=LIGHT_BLUE)
self.geometry("400x150")
self.title("Conundrum")
self.frameA=tk.Frame(master=self,bg=LIGHT_BLUE)
self.letterList=[]
self.answer=r.choice(ninewords)
self.anagram=anagram(self.answer)
for x in range(9):
self.letterList.append(ConundrumDisplay(self.frameA,x))
self.frameA.pack()
self.frameB=tk.Frame(master=self,bg=LIGHT_BLUE)
self.letterEntryList=[]
for y in range(9):
self.letterEntryList.append(ConundrumEntry(self.frameB,y))
self.frameB.pack()
self.timer=tk.Label(master=self,bg=LIGHT_BLUE,font=("Arial",12,"bold"),text="31")
self.update_timer()
self.timer.pack()
self.mainloop()
m.showinfo("Startgame","The game will start when you press OK")
for x in range(9):
self.letterlist[x].add_letter(x,self.anagram)
self.bind("<Key>",self.process_key)
self.bind("Return",self.process_guess)
self.bind("BackSpace",self.process_back)
The upper bit of code is a method from an App class which inherits from tk.Tk
The error is in the super()._ _ init _ _() line in the conundrum class after you press the Conundrum button in the main wn
This conundrum class is obviously the bit of code just below which inherits from tk.Toplevel.
I have used tk.Toplevel before but it hasn't shown the error before.
I have tried to reduce the amount of code that I am posting but if any more of it is necessary to figure out the error, then I can amend the question.
Error Message:
Traceback (most recent call last):
File "/nix/store/2vm88xw7513h9pyjyafw32cps51b0ia1-python3-3.8.12/lib/python3.8/tkinter/__init__.py", line 1892, in __call__
return self.func(*args)
File "main.py", line 50, in start_conundrum
self.Conundrum=Conundrum()
File "main.py", line 55, in __init__
super().__init__()
File "/nix/store/2vm88xw7513h9pyjyafw32cps51b0ia1-python3-3.8.12/lib/python3.8/tkinter/__init__.py", line 2624, in __init__
self.title(root.title())
TypeError: 'Label' object is not callable
The error is telling you exactly what is wrong: you can't call a Label as if it was a function.
You are doing this: self.title(root.title()). root.title is an instance of Label but you are trying to call it as if it was a function. You get the same error if you do something like this:
foo = Label(...)
foo()
Since foo is a Label rather than a function, you can't call it.
If you want to call the title function of the root window, you should not name the label self.title. Name it something else so that you can use the title method of the base class.

How can I implement options in my oop python code?

Help me, I don't know how can I implement options in my oop code, I don't want browser pop up every time I run the code, I have to add headless option but I don't know how
I do know how to make my code headless in functional or imperative paradigm, but I can't figure out how to implement this in oop paradigm, whatever I do, I approach to an error, I don't know what to do, I would be extremely thankful to who guild me to light
my code
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import os
os.environ["PATH"] = "C:\\SeleniumWebDrivers"
op = webdriver.ChromeOptions()
op.add_argument("--disable-blink-features=AutomationControlled")
op.add_argument("headless")
class Avamovie(webdriver.Opera(options=op)):
def __init__(self, teardown=False):
self.teardown = teardown
super(Avamovie, self).__init__()
self.implicitly_wait(15)
self.maximize_window()
self.minimize_window()
def __exit__(self, exc_type, exc_val, exc_tb) -> None:
if self.teardown:
self.quit()
def get_the_page(self):
self.get("https://avamovie17.xyz")
def search_box(self, title):
sbox = self.find_element_by_css_selector("input[placeholder='جستجو']")
sbox.send_keys(title)
sbox.click()
r = self.find_element_by_css_selector("ul[class='search_result_list']")
r = r.find_element_by_tag_name("li").find_element_by_css_selector(
"span[class='title']"
)
r.click()
def download_links(self):
links = self.find_elements_by_css_selector("a[href*='.mkv']")
links = [link.get_attribute("href") for link in links]
print(links)
with Avamovie() as scraper:
scraper.get_the_page()
scraper.search_box("A hero 2021")
scraper.download_links()
my latest error:
Traceback (most recent call last):
File "c:\Users\yasin\Desktop\pf\Projects\Selena\selena.py", line 1, in <module>
from sites.avamovie import Avamovie
File "c:\Users\yasin\Desktop\pf\Projects\Selena\sites\avamovie.py", line 10, in <module>
class Avamovie(webdriver.Opera(options=op)):
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\opera\webdriver.py", line 79, in __init__
OperaDriver.__init__(self, executable_path=executable_path,
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\opera\webdriver.py", line 55, in __init__
ChromiumDriver.__init__(self,
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\chrome\webdriver.py", line 73, in __init__
self.service.start()
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\common\service.py", line 71, in start
cmd.extend(self.command_line_args())
File "C:\Users\yasin\AppData\Roaming\Python\Python310\site-packages\selenium\webdriver\chrome\service.py", line 45, in command_line_args
return ["--port=%d" % self.port] + self.service_args
TypeError: %d format: a real number is required, not dict
I would appreciate any help, thanks guys
You appear to be trying to inherit from an instance of Opera, not the class itself. The options are passed to the call to super().__init__.
class Avamovie(webdriver.Opera):
def __init__(self, options, teardown=False):
self.teardown = teardown
super(Avamovie, self).__init__(options)
self.implicitly_wait(15)
self.maximize_window()
self.minimize_window()
...
with Avamovie(op) as scraper:
scraper.get_the_page()
scraper.search_box("A hero 2021")
scraper.download_links()

Why do I receive an AttributeError even though import, spelling and file location is correct?

I am using PyCharm
All files are in the directory 'venv'
venv
NoteFunction.py
NoteMainApp.py
...
I split up my code in five separate files. One 'main' file, gathering all other files and creating eventually the GUI. The prefix for the files is 'Note' followed an appropriate description.
My problem now is the import of 'NoteTopMenu' into the main file 'NoteMainApp'.
The code is:
import NoteStatusbar as SB
import NoteTopMenu as TM
import NoteWidgets as NW
import tkinter as tk
class MainApp(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self,parent)
super().__init__(parent)
self.topbar = TM.TopMenu(parent)
self.widget = NW.FrontFrames(parent)
self.statusbar = SB.StatusBar(parent)
root = tk.Tk()
MainApp(root).pack(side="top", fill="both")
root.mainloop()
I receive the error message:
Traceback (most recent call last):
File "C:/Users/PycharmProjects/MindNotez/NoteMainApp.py", line 2, in <module>
import NoteTopMenu as TM
File "C:\Users\PycharmProjects\MindNotez\NoteTopMenu.py", line 2, in <module>
import NoteMainApp as Main
File "C:\Users\PycharmProjects\MindNotez\NoteMainApp.py", line 29, in <module>
MainApp(root).pack(side="top", fill="both")
File "C:\Users\PycharmProjects\MindNotez\NoteMainApp.py", line 13, in __init__
self.topbar = TM.TopMenu(parent)
AttributeError: module 'NoteTopMenu' has no attribute 'TopMenu'
The code in NoteTopMenu is:
import NoteMainApp as Main
import NoteWidgets as NW
import tkinter as tk
class TopMenu(NW.FrontFrames):
"""Class creating the top menu bar."""
def __init__(self, master):
super().__init__(master)
# *******Top-Navigation Bar (tnb)**********
tnb = tk.Menu(master)
Main.root.config(menu=tnb)
....
If I comment the NoteTopMenu out in the main file, the code runs without a problem. I checked my spelling but PyCharm also offers me code-completion. Therefore, PyCharm finds the file, the module, my class and other module are imported without an issue. Do you know why the file/module is not being found or fails to be imported?
Full code is here on GitHub: MindNotez
Thank you very much for your help!
You invoke NoteMainApp.py which imports NoteTopMenu.py which imports NoteMainApp.py which does not go on to re-import NoteTopMenu.py (because the import has already started). The import of NoteMainApp.py then goes on to parse the rest of the file. At this point the module NoteTopMenu is defined, but it doesn't have any attributes (because you haven't got round to defining them yet) ... hence the error.
I suggest that NoteTopMenu.py should not import NoteMainApp.py (and if there are any bits which both files need, they should be moved into another file that both can import)

Why crash when derive from QListWidgetItem AND QObject

The following minimal example crashes in pyqt 5.7.1 on windows (copy-paste this in a .py file and run):
from PyQt5.QtWidgets import QListWidgetItem, QListWidget, QApplication
from PyQt5.QtCore import QObject, pyqtSlot, pyqtSignal
class MyListItem(QListWidgetItem):
def __init__(self, obj):
QListWidgetItem.__init__(self, 'example')
obj.sig_name_changed.connect(self.__on_list_item_name_changed)
def __on_list_item_name_changed(self, new_name: str):
self.setText(new_name)
class MyListItem2(QListWidgetItem, QObject):
def __init__(self, obj):
QListWidgetItem.__init__(self, 'example')
QObject.__init__(self)
obj.sig_name_changed.connect(self.pyqt_slot)
#pyqtSlot(str)
def __on_list_item_name_changed(self, new_name: str):
self.setText(new_name)
class Data(QObject):
sig_name_changed = pyqtSignal(str)
class SearchPanel(QListWidget):
def __init__(self, parent=None):
QListWidget.__init__(self, parent)
obj = Data()
hit_item = MyListItem(obj) # OK
hit_item = MyListItem2(obj) # crashes
self.addItem(hit_item)
obj.sig_name_changed.emit('new_example')
app = QApplication([])
search = SearchPanel()
search.show()
app.exec()
Now just comment out the line that says "crashes", and it works fine. Moreover, the list widget shows 'new_example', showing that the signal went through.
Is there a way to make it work with MyListItem2? i.e. I want to be able to decorate the slot with pyqtSlot, which in turn requires (in PyQt 5.7) that I derive item from QObject.
The intent here is that each item in the list has several characteristics that can change (icon, font, text color) based on signals from associated Data instance (each instance actually "lives", in the Qt sense of the term, in a second thread of our application).
This has got nothing to do with pyqtSlot.
The actual problem is that you are trying to inherit from two Qt classes, and that is not generally supported. The only exceptions to this are Qt classes that implement interfaces, and Qt classes that share a common base-class (e.g. QListWidget and QWidget). However, only the former is offically supported, and there are several provisos regarding the latter (none of which are relevant here).
So a Python class that inherits from both QListWidgetItem and QObject just will not work. The main problem occurs when PyQt tries to access attributes that are not defined by the top-level base-class (even when the attribute does not exist). In earlier PyQt versions, this would simply raise an error:
>>> class MyListItem2(QListWidgetItem, QObject): pass
...
>>> x = MyListItem2()
>>> x.objectName()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: could not convert 'MyListItem2' to 'QObject'
>>> x.foo
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: could not convert 'MyListItem2' to 'QObject'
which makes it clear that (in C++ terms) a MyListItem2(QListWidgetItem) cannot be cast to a QObject. Unfortunately, it seems that more recent versions of PyQt5 no longer raise this error, and instead just immediately dump core (which presumably is a bug).
If you really need to use pyqtSlot, one suggestion would be to use composition rather than subclassing. So perhaps something like this:
class ListItemProxy(QObject):
def __init__(self, item, obj):
QObject.__init__(self)
self._item = item
obj.sig_name_changed.connect(self.__on_list_item_name_changed)
#pyqtSlot(str)
def __on_list_item_name_changed(self, new_name: str):
self._item.setText(new_name)
class MyListItem2(QListWidgetItem):
def __init__(self, obj):
QListWidgetItem.__init__(self, 'example')
self._proxy = ListItemProxy(self, obj)

wxPython GridSizer.Add() not working for custom control

I'm trying to create a custom control based on wx.richtext.RichTextCtrl and I'm running into a problem. Whenever I attempt to add the custom control to a sizer, wxPython chokes with the error
Traceback (most recent call last):
File "pyebook.py", line 46, in <module>
frame = MainFrame(None, 'pyebook')
File "pyebook.py", line 14, in __init__
self.mainPanel.GetSizer().Add(ReaderControl(self.mainPanel), 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
File "/usr/local/lib/wxPython-unicode-2.8.11.0/lib/python2.6/site-packages/wx-2.8-mac-unicode/wx/_core.py", line 12685, in Add
return _core_.Sizer_Add(*args, **kwargs)
TypeError: wx.Window, wx.Sizer, wx.Size, or (w,h) expected for item
The custom control is at this time extremely simple and looks like this
class ReaderControl(wx.richtext.RichTextCtrl):
def __init__(self, parent, id=-1, value=''):
wx.richtext.RichTextCtrl(parent, id, value, style=wx.richtext.RE_READONLY, name='ReaderControl')
The code I'm using to add the control to the sizer is:
self.mainPanel.GetSizer().Add(ReaderControl(self.mainPanel), 1, wx.ALIGN_CENTER_VERTICAL | wx.EXPAND)
Any ideas what I'm doing wrong here?
I think you need to call __ init __ explicitly, so you can pass in 'self'. Otherwise, you are just creating a new instance of RichTextCtrl, not initialising your subclass properly.
IOW:
class ReaderControl(wx.richtext.RichTextCtrl):
def __init__(self, parent, id=-1, value=''):
wx.richtext.RichTextCtrl.__init__(self, parent, id, value, style=wx.richtext.RE_READONLY, name='ReaderControl'

Categories