I am a new pyqtgraph users,try to "Embedding widgets inside PyQt applications"following the instructions in http://www.pyqtgraph.org/documentation/how_to_use.html. in my example I promote Graphics view to PlotWidget, then save as "test2.ui", also follow the "crosshair/mouse interaction" example,my code:
import sys
import numpy
from PyQt5 import QtCore, QtGui,uic,QtWidgets
from PyQt5.QtWidgets import *
import pyqtgraph as pg
import os
hw,QtBaseClass=uic.loadUiType("test.ui")
def gaussian(A, B, x):
return A * numpy.exp(-(x / (2. * B)) ** 2.)
class MyApp(QtWidgets.QMainWindow, hw):
def __init__(self):
super().__init__()
self.setupUi(self)
winSize=self.size()
self.view.resize(winSize.width(),winSize.height())
x = numpy.linspace(-5., 5., 10000)
y =gaussian(5.,0.2, x)
self.p=self.view.plot(x,y)
proxy = pg.SignalProxy(self.view.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
self.view.enableAutoRange("xy", True)
def mouseMoved(evt):
print("mouseTest")
mousePoint = self.p.vb.mapSceneToView(evt[0])
label.setText(
"<span style='font-size: 14pt; color: white'> x = %0.2f, <span style='color: white'> y = %0.2f</span>" % (
mousePoint.x(), mousePoint.y()))
if __name__ == "__main__":
app = QtWidgets.QApplication(sys.argv)
window = MyApp()
window.show()
sys.exit(app.exec_())
it seems not get the mouse move event;
after change
proxy = pg.SignalProxy(self.view.scene().sigMouseMoved, rateLimit=60, slot=self.mouseMoved)
to
self.view.scene().sigMouseMoved.connect(self.mouseMoved),
output"MouseTest",but program imediatly crash.
can any one give me some help
Two things:
Re: Crashing
It seems as if you haven't placed a label in the GUI to modify, perhaps your code is seeing this and kicks it back to you. If you're using qtDesigner, it is likely defined as self.label, and in my GUI, I was required to use self.label to reference it.
Re: mouseMoved function
I was just struggling with a similar issue of it not working. I was able to get mine to work by changing the evt[0] to simply evt, something I think they moved to from pyqt4 to pyqt5.
Here's an example of what I was able to get to work:
..........setup code above... IN THE setupUi function:
..........setup code above...
Plotted = self.plot
vLine = pg.InfiniteLine(angle=90, movable=False)
hLine = pg.InfiniteLine(angle=0, movable=False)
Plotted.addItem(vLine, ignoreBounds=True)
Plotted.addItem(hLine, ignoreBounds=True)
Plotted.setMouseTracking(True)
Plotted.scene().sigMouseMoved.connect(self.mouseMoved)
def mouseMoved(self,evt):
pos = evt
if self.plot.sceneBoundingRect().contains(pos):
mousePoint = self.plot.plotItem.vb.mapSceneToView(pos)
self.label.setText("<span style='font-size: 15pt'>X=%0.1f, <span style='color: black'>Y=%0.1f</span>" % (mousePoint.x(),mousePoint.y()))
self.plot.plotItem.vLine.setPos(mousePoint.x())
self.plot.plotItem.hLine.setPos(mousePoint.y()
...the if__name__ =="__main__": function .....
In my case, I did not pass the proxy statement, and instead just went for the sigMouseMoved since it already passes the information the proxy would. I think this was in the example in pyqt5 (and commented out) because it was the change. However, the comment didn't specifically state this.
Related
I have read this question, which is similar and gets me most of the way.
The answer of the code isn't posted, but I believe I have followed the instructions and managed to get it working -- except after it's been opened.
It works perfectly fine immediately after recording, however I want to save the data and read it again for later use: literally every time I run the program and I don't want to have to re-record it every time.
import keyboard
import threading
from keyboard import KeyboardEvent
import time
import json
def record(file='record.txt'):
f = open(file, 'w+')
keyboard_events = []
keyboard.start_recording()
starttime = time.time()
keyboard.wait('esc')
keyboard_events = keyboard.stop_recording()
print(starttime, file=f)
for kevent in range(0, len(keyboard_events)):
print(keyboard_events[kevent].to_json(), file = f)
f.close()
def play(file="record.txt", speed = 1):
f = open(file, 'r')
lines = f.readlines()
f.close()
keyboard_events = []
for index in range(1,len(lines)):
keyboard_events.append(keyboard.KeyboardEvent(**json.loads(lines[index])))
starttime = float(lines[0])
keyboard_time_interval = keyboard_events[0].time - starttime
keyboard_time_interval /= speed
k_thread = threading.Thread(target = lambda : time.sleep(keyboard_time_interval) == keyboard.play(keyboard_events, speed_factor=speed) )
k_thread.start()
k_thread.join()
I am not especially new to coding, or the Python language, but this problem perplexes me. I've tested all the variables and none of them are being sustained outside of the record function.
(I don't fully understand lambda, Threading or **json.loads, but I don't think that's a problem.)
What's going on here?
For extra bonus points, if this is possible to do asynchronously, that'd be amazing. One problem at a time, though.
Just in case anyone else ever has the same problem as me, just tag this at the start of your code. No idea why it works, but it does.
keyboard.start_recording()
temp = keyboard.stop_recording()
You can forget about the temp variable immediately.
I am trying to display both an image and a box with an Entry widget. I can do that, but the window is so large that the widget at the bottom is mostly out of view. I have tried several calls to set the window's size or unmaximize it, but they seem to have no effect. I determined that the problem only occurs when the image is large, but still wonder how to display a large image in a resizable window or, for that matter, to make any changes to the window's geometry from code. All the function call I tried seem to have no effect.
Here is my code:
import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk
from gi.repository import GdkPixbuf
from urllib.request import urlopen
class Display(object):
def __init__(self):
self.window = Gtk.Window()
self.window.connect('destroy', self.destroy)
self.window.set_border_width(10)
# a box underneath would be added every time you do
# vbox.pack_start(new_widget)
vbox = Gtk.VBox()
self.image = Gtk.Image()
response = urlopen('http://1.bp.blogspot.com/-e-rzcjuCpk8/T3H-mSry7PI/AAAAAAAAOrc/Z3XrqSQNrSA/s1600/rubberDuck.jpg').read()
pbuf = GdkPixbuf.PixbufLoader()
pbuf.write(response)
pbuf.close()
self.image.set_from_pixbuf(pbuf.get_pixbuf())
self.window.add(vbox)
vbox.pack_start(self.image, False, False, 0)
self.entry = Gtk.Entry()
vbox.pack_start(self.entry, True,True, 0)
self.image.show()
self.window.show_all()
def main(self):
Gtk.main()
def destroy(self, widget, data=None):
Gtk.main_quit()
a=Display()
a.main()
Most of the posted information seems to pertain to Gtk2 rather than Gtk3, but there is a solution: to use a pix buf loader and set the size:
from gi.repository import Gtk, Gdk, GdkPixbuf
#more stuff
path = config['DEFAULT']['datasets']+'working.png'
with open(path,'rb') as f:
pixels = f.read()
loader = GdkPixbuf.PixbufLoader()
loader.set_size(400,400)
loader.write(pixels)
pb = GdkPixbuf.Pixbuf.new_from_file(path)
self.main_image.set_from_pixbuf(loader.get_pixbuf())
loader.close()
In my new program, I kept having the same lines of code show up, so I decided to make a function, and call it when I want. But I keep getting an error that tells me "my function in not defined". I am new to Python programming and I can't figure it out!
This is my code:
import tkinter as tk
from tkinter import ttk
class GUI(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
#Window_Creation
scr_xloc = int(self.winfo_screenwidth() / 2 - 800 / 2)
scr_yloc = int(self.winfo_screenheight() / 2 - 600 / 2 - 30)
self.geometry("800x600+{}+{}".format(scr_xloc, scr_yloc))
self.minsize(width = 800, height = 600)
...
def Factorial_Calculation():
user_input = int(float(user_input))
import math
factorial_num = math.factorial(user_input)
self.Output_Box.delete("1.0", "end")
self.Output_Box.insert("1.0", str(user_input) + "! = " + str(factorial_num))
def x_Factorial_Loop(self, event):
global user_input
...
Factorial_Calculation()
Your problem is the calling of Factorial_Calculation(), you should call it within the class as self.Factorial_Calculation() but outside of the class is a different thing. Add "self." in front of your called function, as it applies to that class you called it in and pulls up the definition from the class you called it in.
I have managed to use suggested code in order to render HTML from a webpage and then parse, find and use the text as wanted. I'm using PyQt4. However, the webpage I am interested in is updated frequently and I want to rerender the page and check the updated HTML for new info.
I thus have a loop in my pythonscript so that I sort of start all over again. However, this makes the program crash. I have searched the net and found out that this is to be expected, but I have not found any suggestion on how to do it correctly. It must be simple, I guess?
from PyQt4.QtGui import *
from PyQt4.QtCore import *
from PyQt4.QtWebKit import *
class Render (QWebPage):
def __init__(self, url):
self.app = QApplication(sys.argv)
QWebPage.__init__(self)
self.loadFinished.connect(self._loadFinished)
self.mainFrame().load(QUrl(url))
self.app.exec_()
def _loadFinished(self, result):
self.frame = self.mainFrame()
self.app.quit()
r = Render(url)
html = r.frame.toHtml()
S,o when I hit r=Render(url) the second time, it crashes. S,o I am looking for something like r = Rerender(url).
As you might guess, I am not much of a programmer, and I usually get by by stealing code I barely understand. But this is the first time I can't find an answer, so I thought I should ask a question myself.
I hope my question is clear enough and that someone has the answer.
Simple demo (adapt to taste):
import sys, signal
from PyQt4 import QtCore, QtGui, QtWebKit
class WebPage(QtWebKit.QWebPage):
def __init__(self, url):
super(WebPage, self).__init__()
self.url = url
self.mainFrame().loadFinished.connect(self.handleLoadFinished)
self.refresh()
def refresh(self):
self.mainFrame().load(QtCore.QUrl(self.url))
def handleLoadFinished(self):
print('Loaded:', self.mainFrame().url().toString())
# do stuff with html ...
print('Reloading in 3 seconds...\n')
QtCore.QTimer.singleShot(2000, self.refresh)
if __name__ == '__main__':
signal.signal(signal.SIGINT, signal.SIG_DFL)
app = QtGui.QApplication(sys.argv)
webpage = WebPage('http://en.wikipedia.org/')
print('Press Ctrl+C to quit\n')
sys.exit(app.exec_())
I am trying to find the simplest example of a custom widget being written for Gtk-3.
So far the best thing I've found is this (using PyGTK), but it seems to be targeted to Gtk-2.
BTW: I don't care the language it is written in, but if we can avoid C++, much better!
Python3 Gtk3 it is, then:
from gi.repository import Gtk
class SuperSimpleWidget(Gtk.Label):
__gtype_name__ = 'SuperSimpleWidget'
Here is a non-trivial example that actually does something, namely paints its background and draws a diagonal line through it. I'm inheriting from Gtk.Misc instead of Gtk.Widget to save some boilerplate (see below):
class SimpleWidget(Gtk.Misc):
__gtype_name__ = 'SimpleWidget'
def __init__(self, *args, **kwds):
super().__init__(*args, **kwds)
self.set_size_request(40, 40)
def do_draw(self, cr):
# paint background
bg_color = self.get_style_context().get_background_color(Gtk.StateFlags.NORMAL)
cr.set_source_rgba(*list(bg_color))
cr.paint()
# draw a diagonal line
allocation = self.get_allocation()
fg_color = self.get_style_context().get_color(Gtk.StateFlags.NORMAL)
cr.set_source_rgba(*list(fg_color));
cr.set_line_width(2)
cr.move_to(0, 0) # top left of the widget
cr.line_to(allocation.width, allocation.height)
cr.stroke()
Finally, if you really want to derive from Gtk.Widget then you also have to set up a drawing background. Gtk.Misc does that for you, but Gtk.Widget could be a container that doesn't actually draw anything itself. But inquiring minds want to know, so you could do it like so:
from gi.repository import Gdk
class ManualWidget(Gtk.Widget):
__gtype_name__ = 'ManualWidget'
def __init__(self, *args, **kwds):
# same as above
def do_draw(self, cr):
# same as above
def do_realize(self):
allocation = self.get_allocation()
attr = Gdk.WindowAttr()
attr.window_type = Gdk.WindowType.CHILD
attr.x = allocation.x
attr.y = allocation.y
attr.width = allocation.width
attr.height = allocation.height
attr.visual = self.get_visual()
attr.event_mask = self.get_events() | Gdk.EventMask.EXPOSURE_MASK
WAT = Gdk.WindowAttributesType
mask = WAT.X | WAT.Y | WAT.VISUAL
window = Gdk.Window(self.get_parent_window(), attr, mask);
self.set_window(window)
self.register_window(window)
self.set_realized(True)
window.set_background_pattern(None)
Edit and to actually use it:
w = Gtk.Window()
w.add(SimpleWidget())
w.show_all()
w.present()
import signal # enable Ctrl-C since there is no menu to quit
signal.signal(signal.SIGINT, signal.SIG_DFL)
Gtk.main()
Or, more fun, use it directly from the ipython3 REPL:
from IPython.lib.inputhook import enable_gtk3
enable_gtk3()
w = Gtk.Window()
w.add(SimpleWidget())
w.show_all()
w.present()
Here's a tutorial about writing a GTK 3 custom container widget in C: http://ptomato.name/advanced-gtk-techniques/html/custom-container.html It's probably more complicated than you need for writing a simple widget. You might also check out the migration guide from GTK 2 to 3: https://developer.gnome.org/gtk3/stable/gtk-migrating-2-to-3.html
SO far the best reference to:
- understand Gobject (from wich gtk widget derive)
- have some boiler code and c code
https://developer.gnome.org/gobject/stable/howto-gobject.html
I know it's not Python written, but converting from c to python is a piece of cake
(what matter is the algorithm, not the language)