I was toying around with creating custom geometry in Panda3d engine. And next code works 100% correct.
class FooBarTriangle(ShowBase):
def __init__(self):
super(self).__init__()
self.disable_mouse()
self.set_frame_rate_meter(True)
self.accept("escape", sys.exit)
self.accept("space", lambda: print(self.camera.get_pos()))
self.camera.set_pos(0, 0, 10)
self.camera.look_at(0, 0, 0)
self._add_light()
self._add_triangle()
def _add_light(self):
# Adds a point light
pass
def _add_triangle(self):
# Adds a single triangle in a certain place
pass
Mysterious things happen when I remove base.disableMouse() from my code. I expect my camera to be movable and appear in the (0, 0, 10) position, looking at (0, 0, 0). But, instead, camera is in the position (0, 0, 0) and I don't know where does it look.
Why does it happen?
This happens, because Panda3D has a default camera control in place (the default camera driver), if you don't call disableMouse(), Panda3D will not move your camera through calls to camera.set_pos(x, y, z), but only allow movement through the specified controls as can be read up here and here in the manual.
You either have to write your own camera controller if you wish to be able to place your camera anywhere other than (0, 0, 0) through code or just use the controls indicated on the links above to move around the scene.
Related
I want to manually create and save a color-indexed image (palette) as a PNG file, using pygame :
# create the bitmap
res = pygame.Surface((src.width, src.height), depth=8)
# create the palette
res.set_palette([pygame.Color((0, 0, 0, 0)), ...])
pygame.image.save(res, "test.png")
But I get :
error: cannot set palette without pygame.display initialized
on the set_palette line.
Of course, it isn't difficult to initialize some dummy display, but I don't see why it should be the case. Nothing is displayed, and nothing seems display dependant in my code...
Also, it's totally useless to initialize pygame or display when you manipulate 32 bits Surfaces. What's the difference between them ?
The reason is because the pygame source says so :)
But I couldn’t find any reason it was necessary, so I recently removed that check in https://github.com/pygame/pygame/pull/3259.
So this will not be the case in the next pygame release.
Your code is wrong, because you create a surface no alpha channel (no SRCALPHA flag), but set an alpha channel with 0. Set a color without alpha channel:
res.set_palette([pygame.Color((0, 0, 0, 0)), ...])
res.set_palette([pygame.Color((0, 0, 0)), ...])
A pygame.Surface is somehow associated with the display and is created in a format that best suits the display surface. You need to initialize Pygame with pygame.init() or initialize at least the display module with pygame.display.init().
Minimal working example:
import pygame
pygame.display.init()
res = pygame.Surface((1, 1), depth=8)
# create the palette
res.set_palette([pygame.Color((0, 0, 0))])
I am working on a chat GUI, and I'm trying to put a send button on top of the TextView. I'm using a Table, and I'm attaching both widgets to the same place. The positioning of the widgets is determined by the Alignment containers that I'm putting them both in. The problem is that the TextView covers up the image (I'll make it respond to clicks later). I tried making the image's alignment rise in the Z-order by using align2.window.raise_(), but that didn't change anything. I also tried doing all of the .show()'s manually to make sure that the image's came last, but that didn't work either.
How can I keep the TextView from covering up the image while still letting it take up all the room it can get?
Here is my basic code:
align1 = gtk.Alignment(0, 0, 1, 1)
align2 = gtk.Alignment(1)
table = gtk.Table()
window.add(table)
table.attach(align1, 0, 1, 0, 1)
table.attach(align2, 0, 1, 0, 1)
textview = gtk.TextView()
align1.add(textview)
im = gtk.image_new_from_file("/home/commandant/Desktop/send.png")
align2.add(im)
window.connect('destroy', gtk.main_quit)
window.show_all()
gtk.main()
I have three questions that I could really use some help on. Hope I'm not asking too much.
1) I am designing a simple GUI that contains one frame and one panel. Let's say I have two images that I draw on the panel using dc. One image will be continually fade in and out (on a timer), and the second is stationary (doesn't change). The fading is accomplished by changing the opacity of the image and use dc.Clear() before redrawing the new version of the image.
My question is this: how would I draw the fading in/out image without affecting the second image which does not change? It seems like this causes unnecessary drawing as the stationary image will be redrawn alongside the fading image. Could I selectively clear just the first image without affecting the second? This is my drawing function:
def on_paint(self, event):
dc = wx.PaintDC(self)
dc = wx.BufferedDC(dc)
brush = wx.Brush('#3B3B3B')
dc.SetBackground(brush)
dc.Clear()
# Draw the first image (stationary)
dc.DrawBitmap(stationaryBitmap, 120, 0, True)
# Draw the second image (fading)
image = self.image.AdjustChannels(1, 1, 1, self.factoralpha)
fadingBitmap = wx.BitmapFromImage(image)
dc.DrawBitmap(fadingBitmap, 120, 0, True)
2) How can I bind an event to a wx.Image object? I would like to be able to click on the fading in/out image, though I can't seem to assign it an id. The goal is to bind an event similar to what I could do with a wx.StaticBitmap.
self.image = wx.Image("C:\image.png", wx.BITMAP_TYPE_PNG)
# Trying to bind an event, but no ID is assigned
self.Bind(wx.EVT_BUTTON, self.go_button, id=self.image.GetId())
3) Is it possible to place wx.DrawBitmap in a sizer? It appears that it only takes an x,y coordinate pair.
dc.DrawBitmap(bitmap, 120, 0, True)
Thanks everyone.
1) For the Performance, I would recommend using a MemoryDC and update the Drawing only it is required. See here: BufferedCanvas. You may want to use more than 2 buffers because you are using 2 images (see example).
2) I don't know about this, but have you tried to do the binding to a panel and fade the panel in/out?
You can directly paint on a wx.Panel.
Regards
I have an image/pixbuf that I want to draw into a gtk.DrawingArea and refresh frequently, so the blitting operation has to be fast. Doing it the easy way:
def __init__(self):
self.drawing_area = gtk.DrawingArea()
self.image = gtk.gdk.pixbuf_new_from_file("image.png")
def area_expose_cb(self, area, event):
self.drawing_area.window.draw_pixbuf(self.gc, self.image, 0, 0, x, y)
However leads to very slow performance, likely caused by the pixbuf not being in the displays color format.
I had no success with Cairo either, as it seems limited to 24/32bit formats and doesn't have a 16bit format (FORMAT_RGB16_565 is unsupported and deprecated).
What alternatives are there to drawing pictures quickly in Gtk+?
Try creating Pixmap that uses the same colormap as your drawing area.
dr_area.realize()
self.gc = dr_area.get_style().fg_gc[gtk.STATE_NORMAL]
img = gtk.gdk.pixbuf_new_from_file("image.png")
self.image = gtk.gdk.Pixmap(dr_area.window, img.get_width(), img.get_height())
self.image.draw_pixbuf(self.gc, img, 0, 0, 0, 0)
and drawing it to the screen using
dr_area.window.draw_drawable(self.gc, self.image, 0, 0, x, y, *self.image.get_size())
Are you really not generating enough raw speed/throughput? Or is it just that you're seeing flickering?
If it's the latter, perhaps you should investigate double buffering for perfomring your updates instead? Basically the idea is to draw to an invisible buffer then tell the graphics card to use the new buffer.
Maybe check out this page which has some information on double buffering.
It may be worth doing some benchmarking - if you draw with a small area is it still slow?
If it is, it may be worth asking on pygtk or gtk mailing lists...
i'm trying to make a GTK application in python where I can just draw a loaded image onto the screen where I click on it. The way I am trying to do this is by loading the image into a pixbuf file, and then drawing that pixbuf onto a drawing area.
the main line of code is here:
def drawing_refresh(self, widget, event):
#clear the screen
widget.window.draw_rectangle(widget.get_style().white_gc, True, 0, 0, 400, 400)
for n in self.nodes:
widget.window.draw_pixbuf(widget.get_style().fg_gc[gtk.STATE_NORMAL],
self.node_image, 0, 0, 0, 0)
This should just draw the pixbuf onto the image in the top left corner, but nothing shows but the white image. I have tested that the pixbuf loads by putting it into a gtk image. What am I doing wrong here?
You can make use of cairo to do this. First, create a gtk.DrawingArea based class, and connect the expose-event to your expose func.
class draw(gtk.gdk.DrawingArea):
def __init__(self):
self.connect('expose-event', self._do_expose)
self.pixbuf = self.gen_pixbuf_from_file(PATH_TO_THE_FILE)
def _do_expose(self, widget, event):
cr = self.window.cairo_create()
cr.set_operator(cairo.OPERATOR_SOURCE)
cr.set_source_rgb(1,1,1)
cr.paint()
cr.set_source_pixbuf(self.pixbuf, 0, 0)
cr.paint()
This will draw the image every time the expose-event is emited.
I found out I just need to get the function to call another expose event with widget.queue_draw() at the end of the function. The function was only being called once at the start, and there were no nodes available at this point so nothing was being drawn.