I have a problem, but this time it has more relationship with Wxpython than with Tkinter. I don't usually use this module, so I know very little about it.
In the following code, pressing the Enter key in the Tkinter test window will open the windows printing window. If sent to print to PDF, it works perfect.
But if the process is repeated, an error will occur. Below are the test code and the error.
CODE
from threading import Thread
from tkinter import Tk
import wx
def f_imprimir(codigo):
class TextDocPrintout(wx.Printout):
def __init__(self):
wx.Printout.__init__(self)
def OnPrintPage(self, page):
dc = self.GetDC()
ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
ppiScreenX, ppiScreenY = self.GetPPIScreen()
logScale = float(ppiPrinterX)/float(ppiScreenX)
pw, ph = self.GetPageSizePixels()
dw, dh = dc.GetSize()
scale = logScale * float(dw)/float(pw)
dc.SetUserScale(scale, scale)
logUnitsMM = float(ppiPrinterX)/(logScale*25.4)
codigo(dc, logUnitsMM)
return True
class PrintFrameworkSample(wx.Frame):
def OnPrint(self):
pdata = wx.PrintData()
pdata.SetPaperId(wx.PAPER_A4)
pdata.SetOrientation(wx.LANDSCAPE)
data = wx.PrintDialogData(pdata)
printer = wx.Printer(data)
printout = TextDocPrintout()
useSetupDialog = True
if not printer.Print(self, printout, useSetupDialog) and printer.GetLastError() == wx.PRINTER_ERROR:
wx.MessageBox(
"There was a problem printing.\n"
"Perhaps your current printer is not set correctly?",
"Printing Error", wx.OK)
else:
data = printer.GetPrintDialogData()
printout.Destroy()
self.Destroy()
app=wx.App(False)
PrintFrameworkSample().OnPrint()
def funcion(dc, MM):
dc.DrawText("hola mundo", MM*16, MM*73)
def imprimir(codigo):
t = Thread(target=f_imprimir, args=(codigo,))
t.start()
Tk().bind("<Return>", lambda Event:imprimir(funcion))
ERROR
File "C:\Users\DANTE\Google Drive\JNAAB\DESARROLLO\pruebas\t\s\prueba.py", line 11, in OnPrintPage
dc = self.GetDC()
AttributeError: 'TextDocPrintout' object has no attribute 'GetDC'
Does anyone know the solution to the problem? Thank you.
I did the tests and this code should be a solution for all the problems I have, including this one. I suppose this works because it gives Tkinter time to update the window before the Printer Selection Window starts.
from tkinter import Tk, Entry
import wx
def f_imprimir(v,codigo):
class TextDocPrintout(wx.Printout):
"""
A printout class that is able to print simple text documents.
Does not handle page numbers or titles, and it assumes that no
lines are longer than what will fit within the page width. Those
features are left as an exercise for the reader. ;-)
"""
def __init__(self):#, text, title, margins):
wx.Printout.__init__(self)#, title)
self.numPages = 1
def HasPage(self, page):
return page <= self.numPages
def GetPageInfo(self):
return (1, self.numPages, 1, self.numPages)
def CalculateScale(self, dc):
# Scale the DC such that the printout is roughly the same as
# the screen scaling.
ppiPrinterX, ppiPrinterY = self.GetPPIPrinter()
ppiScreenX, ppiScreenY = self.GetPPIScreen()
logScale = float(ppiPrinterX)/float(ppiScreenX)
# Now adjust if the real page size is reduced (such as when
# drawing on a scaled wx.MemoryDC in the Print Preview.) If
# page width == DC width then nothing changes, otherwise we
# scale down for the DC.
pw, ph = self.GetPageSizePixels()
dw, dh = dc.GetSize()
scale = logScale * float(dw)/float(pw)
# Set the DC's scale.
dc.SetUserScale(scale, scale)
# Find the logical units per millimeter (for calculating the
# margins)
self.logUnitsMM = float(ppiPrinterX)/(logScale*25.4)
def OnPreparePrinting(self):
# calculate the number of pages
dc = self.GetDC()
self.CalculateScale(dc)
def OnPrintPage(self, page):
codigo(self.GetDC(), self.logUnitsMM)
return True
class PrintFrameworkSample(wx.Frame):
def __init__(self):
wx.Frame.__init__(self)
# initialize the print data and set some default values
self.pdata = wx.PrintData()
self.pdata.SetPaperId(wx.PAPER_A4)
self.pdata.SetOrientation(wx.PORTRAIT)
def OnPrint(self):#, evt):
data = wx.PrintDialogData(self.pdata)
printer = wx.Printer(data)
printout = TextDocPrintout()
useSetupDialog = True
if not printer.Print(self, printout, useSetupDialog) and printer.GetLastError() == wx.PRINTER_ERROR:
wx.MessageBox(
"Hubo un problema al imprimir.\n"
"Su impresora está configurada correctamente?",
"Error al Imprimir", wx.OK)
else:
data = printer.GetPrintDialogData()
self.pdata = wx.PrintData(data.GetPrintData()) # force a copy
printout.Destroy()
app=wx.App(False)
PrintFrameworkSample().OnPrint()
app.MainLoop()
entrada["state"] = "normal"
def funcion(dc, MM):
dc.DrawText("hola mundo", MM*16, MM*73)
v=Tk()
entrada=Entry(v)
entrada.pack()
after = lambda:v.after(10,lambda:f_imprimir(v,funcion))
v.bind("<Return>", lambda Event:(entrada.config(state="disable"),after()))
Related
I'm currently working on a project to download a bunch of hentai using api requests. The code works, but whenever i found a bug, I always had to use the search function to see where variables or funktions i created are located in the code. Then I had the idea, to change the color of the funktions, so that if i wanted to look for the funktion Sample_funktion i would just have to look for the color red.
from time import sleep
from keyboard import is_pressed
import random
import win32clipboard
# SETTINGS
pyautogui.PAUSE = 0.5
reloadtime = 1
s2tv = 1
nothing = 1786, 327
filedownload = "720p.png"
# VARIABLES
captchas_destroyed = 0
fucked_by_captchas = 0
data = None
def get_URL():
global data
pyautogui.hotkey('ctrl', 'l')
pyautogui.hotkey('ctrl', 'c')
win32clipboard.OpenClipboard()
data = win32clipboard.GetClipboardData()
win32clipboard.CloseClipboard()
def p720_checker():
p720 = pyautogui.locateCenterOnScreen(filedownload, grayscale=True, confidence=0.95)
if p720 is not None:
pyautogui.click(p720)
def check4ads():
ads = pyautogui.locateCenterOnScreen('close_ad.png', grayscale=True, confidence=0.95)
if ads is not None:
pyautogui.click(ads)
def yellow_download():
yellow_download_kink = pyautogui.locateCenterOnScreen('getdownloadlinks.png', grayscale=True, confidence=0.9)
if yellow_download_kink is not None:
pyautogui.click(yellow_download_kink)
def cloud_download_checker():
download_cloud = pyautogui.locateCenterOnScreen("gray_cloud.png", grayscale=True, confidence=0.9)
if download_cloud is not None:
pyautogui.click(download_cloud)
def randomclick(box):
x_click = int(random.uniform(box.left, box.left + box.width))
y_click = int(random.uniform(box.top, box.top + box.height))
pyautogui.moveTo(x_click, y_click, duration=random.uniform(0.1, 0.2))
sleep(random.uniform(0.2, 0.3))
pyautogui.click()
sleep(random.uniform(1, 2))
def moverandomasf():
for hot_single_moms in range(random.randint(2, 6)):
x_click = random.randint(1, 1080)
y_click = random.randint(1, 1080)
pyautogui.moveTo(x=x_click, y=y_click, duration=random.uniform(0.2, 0.5))
def reload():
pyautogui.hotkey('ctrl', 'r')
sleep(reloadtime)
def s2t():
sleep(s2tv)
def andere_tabs_schließen():
pyautogui.hotkey('alt', 'o')
sleep(s2tv)
def captcha_checka():
global captchas_destroyed, fucked_by_captchas
captchabox = pyautogui.locateOnScreen("Roboterfeld.png", grayscale=False, confidence=0.9)
if captchabox is not None:
moverandomasf()
randomclick(captchabox)
if pyautogui.locateCenterOnScreen("imnotarobotiswear.png", grayscale=True, confidence=0.9):
print("I DESTROYED DA CAPTCHA BADABABOOM")
captchas_destroyed += 1
elif pyautogui.locateCenterOnScreen("fucked_by_captcha.png", grayscale=True, confidence=0.9):
print("I just got fucked by the captcha... rest in pieces")
reload()
fucked_by_captchas += 1
captcha_checka()
else:
print("No captcha that I can destroy!")
while True:
if is_pressed("ü"):
s2t()
while not is_pressed("ü"):
check4ads()
pyautogui.scroll(-120)
gay_heart = pyautogui.locateCenterOnScreen("gray_heart.png", grayscale=False, confidence=0.9)
if gay_heart is not None:
pyautogui.click(gay_heart)
cloud_download_checker()
s2t()
check4ads()
captcha_checka()
yellow_download()
s2t()
p720_checker()
Sample of my code
Is this possible in pycharm 2020.3.3?
Kind regards, Alupy
As far as I understand, Pycharm does not currently support separate colors for specific functions. It does support using a single color for ALL function definitions and another single color for ALL function calls.
I would start becoming familiar with the actions 'Find Usage', 'Find Usages', 'Find Usages in File', and 'Show Usages'. These will all help you locate where a function is being used.
I also posted in the pyqtgraph forum here.
My overall goal is to have several clickable regions overlaid on an image, and if the plot boundary of any region is clicked I get a signal with the ID of that region. Something like this:
If I use only one PlotDataItem with nan-separated curves then each boundary sends the same signal. However, using a separate PlotDataItem for each boundary makes the application extremely sluggish.
I ended up subclassing ScatterPlotItem and rewriting the pointsAt function, which does what I want. The problem now is I can't figure out the appropriate way to change the ScatterPlotItem's boundingRect. Am I on the right approach? Is there a better way of doing this?
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
class CustScatter(pg.ScatterPlotItem):
def pointsAt(self, pos: QtCore.QPointF):
"""
The default implementation only checks a square around each spot. However, this is not
precise enough for my needs. It also triggers when clicking *inside* the spot boundary,
which I don't want.
"""
pts = []
for spot in self.points(): # type: pg.SpotItem
symb = QtGui.QPainterPath(spot.symbol())
symb.translate(spot.pos())
stroker = QtGui.QPainterPathStroker()
mousePath = stroker.createStroke(symb)
# Only trigger when clicking a boundary, not the inside of the shape
if mousePath.contains(pos):
pts.append(spot)
return pts[::-1]
"""Make some sample data"""
tri = np.array([[0,2.3,0,1,4,5,0], [0,4,4,8,8,3,0]]).T
tris = []
xyLocs = []
datas = []
for ii in np.arange(0, 16, 5):
curTri = tri + ii
tris.append(curTri)
xyLocs.append(curTri.min(0))
datas.append(ii)
def ptsClicked(item, pts):
print(f'ID {pts[0].data()} Clicked!')
"""Logic for making spot shapes from a list of (x,y) vertices"""
def makeSymbol(verts: np.ndarray):
outSymbol = QtGui.QPainterPath()
symPath = pg.arrayToQPath(*verts.T)
outSymbol.addPath(symPath)
# From pyqtgraph.examples for plotting text
br = outSymbol.boundingRect()
tr = QtGui.QTransform()
tr.translate(-br.x(), -br.y())
outSymbol = tr.map(outSymbol)
return outSymbol
app = pg.mkQApp()
pg.setConfigOption('background', 'w')
symbs = []
for xyLoc, tri in zip(xyLocs, tris):
symbs.append(makeSymbol(tri))
"""Create the scatterplot"""
xyLocs = np.vstack(xyLocs)
tri2 = pg.PlotDataItem()
scat = CustScatter(*xyLocs.T, symbol=symbs, data=datas, connect='finite',
pxMode=False, brush=None, pen=pg.mkPen(width=5), size=1)
scat.sigClicked.connect(ptsClicked)
# Now each 'point' is one of the triangles, hopefully
"""Construct GUI window"""
w = pg.PlotWindow()
w.plotItem.addItem(scat)
plt: pg.PlotItem = w.plotItem
plt.showGrid(True, True, 1)
w.show()
app.exec()
Solved! It turns out unless you specify otherwise, the boundingRect of each symbol in the dataset is assumed to be 1 and that the spot size is the limiting factor. After overriding measureSpotSizes as well my solution works:
import numpy as np
import pyqtgraph as pg
from pyqtgraph.Qt import QtCore, QtGui
class CustScatter(pg.ScatterPlotItem):
def pointsAt(self, pos: QtCore.QPointF):
"""
The default implementation only checks a square around each spot. However, this is not
precise enough for my needs. It also triggers when clicking *inside* the spot boundary,
which I don't want.
"""
pts = []
for spot in self.points(): # type: pg.SpotItem
symb = QtGui.QPainterPath(spot.symbol())
symb.translate(spot.pos())
stroker = QtGui.QPainterPathStroker()
mousePath = stroker.createStroke(symb)
# Only trigger when clicking a boundary, not the inside of the shape
if mousePath.contains(pos):
pts.append(spot)
return pts[::-1]
def measureSpotSizes(self, dataSet):
"""
Override the method so that it takes symbol size into account
"""
for rec in dataSet:
## keep track of the maximum spot size and pixel size
symbol, size, pen, brush = self.getSpotOpts(rec)
br = symbol.boundingRect()
size = max(br.width(), br.height())*2
width = 0
pxWidth = 0
if self.opts['pxMode']:
pxWidth = size + pen.widthF()
else:
width = size
if pen.isCosmetic():
pxWidth += pen.widthF()
else:
width += pen.widthF()
self._maxSpotWidth = max(self._maxSpotWidth, width)
self._maxSpotPxWidth = max(self._maxSpotPxWidth, pxWidth)
self.bounds = [None, None]
"""Make some sample data"""
tri = np.array([[0,2.3,0,1,4,5,0], [0,4,4,8,8,3,0]]).T
tris = []
xyLocs = []
datas = []
for ii in np.arange(0, 16, 5):
curTri = tri + ii
tris.append(curTri)
xyLocs.append(curTri.min(0))
datas.append(ii)
def ptsClicked(item, pts):
print(f'ID {pts[0].data()} Clicked!')
"""Logic for making spot shapes from a list of (x,y) vertices"""
def makeSymbol(verts: np.ndarray):
plotVerts = verts - verts.min(0, keepdims=True)
symPath = pg.arrayToQPath(*plotVerts.T)
return symPath
app = pg.mkQApp()
pg.setConfigOption('background', 'd')
symbs = []
for xyLoc, tri in zip(xyLocs, tris):
symbs.append(makeSymbol(tri))
"""Create the scatterplot"""
xyLocs = np.vstack(xyLocs)
tri2 = pg.PlotDataItem()
scat = CustScatter(*xyLocs.T, symbol=symbs, data=datas, connect='finite',
pxMode=False, brush=None, pen=pg.mkPen(width=5), size=1)
scat.sigClicked.connect(ptsClicked)
# Now each 'point' is one of the triangles, hopefully
"""Construct GUI window"""
w = pg.PlotWindow()
w.plotItem.addItem(scat)
plt: pg.PlotItem = w.plotItem
plt.showGrid(True, True, 1)
w.show()
app.exec()
The code bellow try to embed visvis figure in a wx application to make a movie with 3D data. The problem is that everytime I rum the code, I get the error
"./src/unix/glx11.cpp(86): assert "xid" failed in SetCurrent(): window
must be shown" right after calling Figure = app.GetFigureClass()
self.fig = Figure(self)
I spent some time researching this error, but none of the answers suited me. Does anyone knows how to fix it?
import wx
import h5py
import numpy as np
import visvis as vv
app = vv.use('wx')
class CPlot3D (wx.Frame) :
"""
Class for plotting 3D Dirac
"""
def data_for_plotting (self, frame_number) :
"""
Load the data to be plotted for the frame with the frame_number
"""
frame = str(self.frame_names[frame_number])
return self.f[frame][...]
def draw_curent_frame (self, event=None) :
"""
Display the current frame
"""
# Load data
data = self.data_for_plotting (self.frame_number.GetValue())
try :
self.volume_plot.SetData (data)
except AttributeError :
vv.clf()
self.volume_plot = vv.volshow (data, clim=(self.global_min, self.global_max), renderStyle='mip', cm=vv.CM_JET)
a = vv.gca()
vv.ColormapEditor(a)
def GetTicks (axis_num, min_val, max_val, label_format="%.2f") :
size = data.shape[axis_num]
# Number of ticks
nticks = int(np.ceil(np.log2(size)))
nticks += 1 - nticks % 2 # Make <nticks> odd
ticks_position = np.linspace(0, size-1, nticks)
ticks_label = map( lambda x : label_format % x, np.linspace(min_val, max_val, nticks) )
return dict( zip(ticks_position, ticks_label) )
a.axis.xTicks = GetTicks(0, self.x_min, self.x_max)
a.axis.xLabel = "x (rel. units)"
a.axis.yTicks = GetTicks(1, self.y_min, self.y_max)
a.axis.yLabel = "y (rel. units)"
a.axis.zTicks = GetTicks(2, self.z_min, self.z_max)
a.axis.zLabel = "z (rel. units)"
self.fig.Draw()
def __init__ (self, parent, file_name, title="Plot Dirac 3D") :
# Open files
self.f = h5py.File (file_name, 'r')
# Extract the dimension
self.x_gridDIM = int(self.f['x_gridDIM'][...])
self.y_gridDIM = int(self.f['y_gridDIM'][...])
self.z_gridDIM = int(self.f['z_gridDIM'][...])
self.dx = self.f['dx'][...]
self.x_min = self.f['x_min'][...]
self.x_max = self.x_min + self.x_gridDIM * self.dx
self.y_min = self.f['y_min'][...]
self.y_max = self.y_min + self.y_gridDIM * self.dx
self.z_min = self.f['z_min'][...]
self.z_max = self.z_min + self.z_gridDIM * self.dx
# Collect the frame names
self.frame_names = []
for key in self.f.keys () :
try : self.frame_names.append (int(key))
except ValueError: pass
self.frame_names.sort ()
print "\nGet global maximum and minimum..."
# Find the min and max values in all the frames
for frame_number in range(len(self.frame_names)) :
data = self.data_for_plotting (frame_number)
try :
self.global_min = min( self.global_min, data.min() )
self.global_max = max( self.global_max, data.max() )
except AttributeError :
self.global_min = data.min()
self.global_max = data.max()
print "\nStart animation..."
# Create GUI
dw, dh = wx.DisplaySize()
wx.Frame.__init__ (self, parent, title=title, size=(0.4*dw, 0.6*dh) )
self.ConstructGUI ()
self.Center()
self.Show ()
wx.EVT_CLOSE(self, self.on_close)
self.On_animation_button ()
def on_close (self, event) :
try : self.animation_timer.Stop()
except AttributeError : pass
self.Destroy()
def ConstructGUI (self) :
"""
Make a GUI
"""
######################### Navigation bar ##############################
panel = wx.Panel(self)
boxsizer = wx.BoxSizer (wx.HORIZONTAL)
# Frame number indicator
boxsizer.Add (wx.StaticText(panel, label="Frame Number:"))
self.frame_number = wx.SpinCtrl (panel, value="0", min=0, max=len(self.frame_names)-1)
self.frame_number.Bind (wx.EVT_SPINCTRL, self.draw_curent_frame )
boxsizer.Add (self.frame_number)
# Go to the beginning button
self.go_beginnign_button = wx.Button (panel, label="<<")
self.Bind (wx.EVT_BUTTON, self.go_to_beginning, self.go_beginnign_button)
boxsizer.Add (self.go_beginnign_button)
# Animation button
self.animation_button_start_label = "Play animation "
self.animation_button_stop_label = "STOP animation"
self.animation_button = wx.Button (panel, label=self.animation_button_start_label)
self.Bind (wx.EVT_BUTTON, self.On_animation_button, self.animation_button)
boxsizer.Add (self.animation_button)
# Go to the end button
self.go_end_button = wx.Button (panel, label=">>")
self.Bind (wx.EVT_BUTTON, self.go_to_end, self.go_end_button)
boxsizer.Add (self.go_end_button)
panel.SetSizer (boxsizer)
############################# Setting up visvis binding #######################################
Figure = app.GetFigureClass()
self.fig = Figure(self)
################################### Layout #####################################################
sizer = wx.BoxSizer (wx.VERTICAL)
sizer.Add (panel, flag=wx.CENTER)
sizer.Add(self.fig._widget, 1, flag=wx.EXPAND)
self.SetSizer(sizer)
self.SetAutoLayout(True)
self.Layout()
def On_animation_button (self, event=None) :
"""
<self.animation_button> was clicked
"""
if self.animation_button.GetLabel() == self.animation_button_start_label :
# Begin playing animation
# Set up timer for animation
timer_id = wx.NewId ()
self.animation_timer = wx.Timer (self, timer_id)
self.animation_timer.Start (200)
def on_animation_timer (event) :
self.draw_curent_frame()
position = self.frame_number.GetValue()
if position > len(self.frame_names)-2 : self.On_animation_button ()
else : self.frame_number.SetValue (position+1)
wx.EVT_TIMER (self, timer_id, on_animation_timer)
# Channing the button's label
self.animation_button.SetLabel(self.animation_button_stop_label)
else : # Stop playing animation
self.animation_timer.Stop ()
del self.animation_timer
# Channing the button's label
self.animation_button.SetLabel(self.animation_button_start_label)
def go_to_beginning (self, event) :
"""
<self.go_beginnign_button> was clicked
"""
self.frame_number.SetValue (0)
self.draw_curent_frame()
def go_to_end (self, event) :
"""
<self.go_end_button> was clicked
"""
self.frame_number.SetValue (len(self.frame_names)-1)
self.draw_curent_frame()
if __name__ == '__main__' :
import sys
app.Create()
# Loading files
if len(sys.argv) <> 2 :
openFileDialog = wx.FileDialog(None, "Open HDF5 file to load 3D Dirac", "", "",
"HDF5 files (*.hdf5)|*.hdf5", wx.FD_OPEN | wx.FD_FILE_MUST_EXIST | wx.FD_CHANGE_DIR)
# Check whether user canceled
if openFileDialog.ShowModal() == wx.ID_CANCEL:
print "Error: file name is needed as argument"
exit()
else : filename = openFileDialog.GetPath()
else : filename = sys.argv[1]
CPlot3D (None, filename)
app.Run ()
When you call On_animation_button() manually, your frame is not actually shown yet, even though you had called Show() on it because, at least with X11, showing happens asynchronously. So you need to delay calling it until later. This can be done by e.g. binding a lambda doing this to EVT_SIZE event (because by the time you get it, the window is already initialized) or just by using CallAfter().
Drone's motion is not stable with rostopics...what can I do ?
import rospy
import time
#import library untuk mengirim command dan menerima data navigasi dari quadcopter
from geometry_msgs.msg import Twist
from std_msgs.msg import String
from std_msgs.msg import Empty
from ardrone_autonomy.msg import Navdata
#import class status untuk menentukan status ddari quadcopter
from drone_status import DroneStatus
COMMAND_PERIOD = 1000
class AutonomousFlight():
def __init__(self):
self.status = ""
rospy.init_node('forward', anonymous=False)
self.rate = rospy.Rate(10)
self.pubTakeoff = rospy.Publisher("ardrone/takeoff",Empty, queue_size=10)
self.pubLand = rospy.Publisher("ardrone/land",Empty, queue_size=10)
self.pubCommand = rospy.Publisher('cmd_vel',Twist, queue_size=10)
self.command = Twist()
#self.commandTimer = rospy.Timer(rospy.Duration(COMMAND_PERIOD/1000.0),self.SendCommand)
self.state_change_time = rospy.Time.now()
rospy.on_shutdown(self.SendLand)
def SendTakeOff(self):
self.pubTakeoff.publish(Empty())
self.rate.sleep()
def SendLand(self):
self.pubLand.publish(Empty())
def SetCommand(self, linear_x, linear_y, linear_z, angular_x, angular_y, angular_z):
self.command.linear.x = linear_x
self.command.linear.y = linear_y
self.command.linear.z = linear_z
self.command.angular.x = angular_x
self.command.angular.y = angular_y
self.command.angular.z = angular_z
self.pubCommand.publish(self.command)
self.rate.sleep()
if __name__ == '__main__':
try:
i = 0
uav = AutonomousFlight()
while not rospy.is_shutdown():
uav.SendTakeOff()
if i <= 30 :
uav.SetCommand(0,0,1,0,0,0)
i+=1
elif i<=60 :
uav.SetCommand(0,0,0,0,0,0)
i+=1
else:
uav.SendLand()
except rospy.ROSInterruptException:
pass
I need to just takeoff, go up and go to hover mode,
uav.SendTakeOff()
if i <= 30 :
uav.SetCommand(0,0,1,0,0,0)
i+=1
elif i<=60 :
uav.SetCommand(0,0,0,0,0,0)
after take off, this code makes the drone go to little back and some random motion and going up and going to hover mode. How can I fix this ?
I've just started programming in Python and have therefore had an attempt at a simple GUI that consists of a meter (rev counter) and a bar graph. This all works (the code is attached below). However I'm getting very bad flicker due to the screen refreshing (Windows XP). I know I need to use a Buffered DC however I can't work out from all the posts what I actually need to do.
However my assumptions are:
Initially create a Memory DC for the Buffered image to 'reside' in and then
Instantiate the Buffered DC
Bind the On Paint to the Buffered DC.
To provide the relevant meter face (scale) I've drawn it all in Autocad and have then converted it to a jpg (HMIV0.2.bmp) upon which the bar graph and meter needle are superimposed.
As you'll note I'm using the Refresh at the end of my loop and I'm wondering if this is 'bad practice'. However my intention is for the program to free run and 'pick up' the relevant values (revs) on each pass of the loop. Thereby having no external Event to trigger the paint.
Any advise or pointer in the right direction are highly appreciated...I bought Cody Precord's 'Wx.Python 2.8 Application Development Cookbook' in the hope of some inspiration but alas.
import wx
import random
import time
import math
def Data():
data_value =random.randint(0,400)
return data_value
def Pointer():
meter_value =float(random.randint(0,260))
Needle_centre_x = 253
Needle_centre_y = 239
Needle_length = float(125)
Needle_sweep = math.radians(214) #Number of degrees (converted to radians) that the needle is to deflect through
Meter_max_scale = 260 # maximum value on the meter scale
lo_reflect = float(20) # Meter reading that are less than this value are below the horizontal-Lo
Angle_per_digit = Needle_sweep / Meter_max_scale # Angle_per_digit is in radians
print '*******************NEW CYCLE*****************************'
print 'The meter value is ' +str(meter_value)
Start_displac = Angle_per_digit * lo_reflect
needle_ang = -1*(Start_displac -(meter_value * Angle_per_digit))
Needle_x = Needle_length * (math.cos(needle_ang))
Needle_y = Needle_length * (math.sin(needle_ang))
needle_degrees = math.degrees(needle_ang)
anglea = needle_ang - math.pi/2
angleb = needle_ang + math.pi/2
base_x = 10*(math.cos(anglea))
base_y = 10*(math.sin(anglea))
print 'The needle angle is' + str(needle_degrees)
print 'Angle A is ' + str(math.degrees(anglea))
print 'Angle B is ' + str(math.degrees(angleb))
print 'The needle deflection angle is ' + str(math.degrees(needle_ang))
basea_y = int(Needle_centre_y- base_y)
basea_x = int(Needle_centre_x - base_x)
baseb_y = int(Needle_centre_y + base_y)
baseb_x = int(Needle_centre_x + base_x)
needle_y = int(Needle_centre_y - Needle_y)
needle_x = int(Needle_centre_x - Needle_x)
Needle = [Needle_centre_x,Needle_centre_y,needle_x,needle_y,basea_x,basea_y,baseb_x,baseb_y] #Needle = [x1,y1,x2,y2,pointa_y,pointa_x,pointb_y,pointb_x]
return Needle
class MyPanel(wx.Panel):
def __init__(self, parent):
wx.Panel.__init__(self, parent,pos = (0,0), size = (800,500))
self.Bind(wx.EVT_PAINT, self.OnPaint)
def OnPaint(self, data_value):
data_value = Data()
dc = wx.PaintDC(self)
bmp = wx.Bitmap("HMIV0.2.bmp")
dc.DrawBitmap(bmp, 0, 0)
if data_value > 300:
dc.SetBrush(wx.RED_BRUSH)
dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2)
dc.SetBrush(wx.BLUE_BRUSH)
dc.DrawRoundedRectangle(12,450,40,-1*300,2)
dc.SetBrush(wx.GREEN_BRUSH)
dc.DrawRoundedRectangle(12,450,40,-1*200,2)
if data_value < 300 and data_value > 200 :
dc.SetBrush(wx.BLUE_BRUSH)
dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2)
dc.SetBrush(wx.GREEN_BRUSH)
dc.DrawRoundedRectangle(12,450,40,-1*200,2)
if data_value < 200:
dc.SetBrush(wx.GREEN_BRUSH)
dc.DrawRoundedRectangle(12,450,40,-1*(data_value),2)
dc.SetBrush(wx.BLUE_BRUSH)
HMI_needle = Pointer()
print 'the contents of HMI needle are' + str(HMI_needle)
print 'Needle_centre_x,Needle_centre_y,needle_x,needle_y,basea_x,basea_y,baseb_x,baseb_y'
print type(HMI_needle)
Points = [(HMI_needle[2],HMI_needle[3]),(HMI_needle[4],HMI_needle[5]),(HMI_needle[6],HMI_needle[7])]
dc.DrawPolygon(Points)
dc.DrawCircle(253,239,20)
time.sleep(0.1)
self.Refresh()
class MyFrame(wx.Frame):
def __init__(self, parent, title, size):
wx.Frame.__init__(self, parent, wx.ID_ANY, title, wx.DefaultPosition, size,)
bitmap = wx.Bitmap("Background.jpg", type=wx.BITMAP_TYPE_JPEG)
self.bitmap =wx.StaticBitmap(self,bitmap =bitmap)
self.Panel = MyPanel(self)
app = wx.PySimpleApp(redirect=False, filename = "C:\output.txt", clearSigInt=True)
frame = MyFrame(None,"WxPaint", size=(800,500))#size=(800,480))
frame.Show()
app.SetTopWindow(frame)
app.MainLoop()
Use wx.BG_STYLE_CUSTOM on your wx.Panel
Use wx.AutoBufferedPaintDC in your OnPaint handler
See my example code here:
Best Canvas for WxPython
It is rarely good practice to put a delay in an event handler, mostly because it prevents other events from being handled. Instead of ending your OnPaint handler with:
time.sleep(0.1)
self.Refresh()
you should use:
wx.CallLater(100,self.Refresh)
In addition, I have found to avoid flicker, I disable background erase with:
self.Bind(wx.EVT_ERASE_BACKGROUND, lambda x: 0)