I'm tinkering around with tkinter, and have used it to make some dynamic graphics based on a dataset.
I started of with an arbitrary sized canvas of 1000x1000 pixels, and now I have my images made, I wondered if there is was anyway to crop the canvas around the unoccupied parts of the edges.
I think of a couple of ways to achieve this, one would be to trim each edge until an object is hit, however, I think this wouldn't work because as far as I can tell the objects are directly addressed onto the canvas location, so any changes to the canvas in the top RHS would just result in objects moving in concert, another would be to (somehow) group all the objects into a single named object, get the borders and a somehow redraw the lot on a newly sized canvas.
I wondered if anyone had any ideas or done this before?
The bbox method of the canvas gives you the bounding box (opposite corners) of an object or objects on the canvas. So, my_canvas.bbox("all") will return you a rectangle that encompasses all of the items on the canvas. According to the official Tk documentation, this method "may overestimate the actual bounding box by a few pixels"
I'm not sure exactly what you mean by "crop" in the context of this question, but since you know the x/y of the upper left corner of the objects, you can use the move method to move all objects by -x1/-y1 pixels to move everything to the upper left corner.
Related
I'm creating GUI using python tkinter to visualize Road Scenarios (the main vehicle & close by vehicles). I draw in the canvas lines to give road top view (as the Picture below).
The user can insert a rectangle (vehicle) then move it freely on the canvas.
What I want is: after the user moves the rectangle to where ever he wants, the y coordination of the rectangle will relocate to the nearest lane, to have a nice looking png at the end.
My thought about it:
Divide the canvas to regions (each Region represent a lane)
Create a function which knows when the rectangle finished moving, then modify the y coordination of it to the nearest Region (lane).
Not sure how to apply this in Code though. Any useful canvas functions or another approach are much appreciated.
The approach I mentioned at the question worked for me.
A list identifing the y-axis sides of each Region was created.
After creating the items needed, they all share a common Tag.
Choose which part of the items you want to consider the original Point (which will be used later as the item's current location). Canvas.bboc(CURRENT) can be sufficient to do that.
Detect when does the item enter a Region, by comparing if the item's current Location is within the boundaries of a Region.
Use Canvas.coords() or Cancas.move() methods to move the items at the middle of the regoin they have entered.
I didn't find a previous question that seemed to suit what I am asking, but I may not be asking the right thing either.
I have two rectangles, one larger and one smaller. The smaller one can be moved and resized, but I need it contained inside the larger one. But I am having a hard time keeping it inside of the larger one. I can detect when it moves outside of the larger rectangle, but I cannot figure out the method needed to keep it contained without moving outside of the bounding box.
I am currently working python/pyqt4 in a qgraphicsview/scene.
For a working example: In the program gimp, the cropping tool box cannot move outside of the image that is displayed. But it can be moved and resized up to the image's size. That's what I'm aiming for.
I am coding for a mouse drag and drop effect on images. Meanwhile, I want to take record of the upper-left point of image each time I dragged and dropped it, are there any ways to get it?
What methods are you using to draw the images? It's hard to answer this question without that.
If you aren't already doing this, you could use a class to hold data about your image, such as position and geometry.
If you derive your classes from pygame.sprite.Sprite , you can get the position by guy.rect. Depending on if you want center, or toplef, or the full rect:
guy.rect.topleft or guy.rect.center or guy.rect
Someone know if it's possible to change the color of a pixel in a canvas without using un object, so without using something like canvas.create_oval or canvas.create_rectangle ?
There is no way to color a pixel other than to create a 1x1 pixel object of some sort. And yes, at some point you will experience performance problems. The canvas simply wasn't designed to be used this way.
If you're really needing to create a large area in which you can manage individual pixels, you can create a canvas with a single image that is the same size as the canvas. You can then set the color of individual pixels on the image through the photo image interface.
Within tkinter itself, it's impossible.
Even if you manage to change a pixel on canvas window (which is possible with X11 and Windows APIs in a platform-dependent way), you'd have to ensure it's repainted properly.
You can, of course, place a frame of size 1x1 over the canvas, with a background color you want. This way, pixel is "changed" and no canvas object is created. If there's a real (though strange) problem behind a question, this trick could be a solution.
I'm coding a game where the viewport follows the player's ship in a finite game world, and I am trying to make it so that the background "wraps" around in all directions (you could think of it as a 2D surface wrapped around a sphere - no matter what direction you travel in, you will end up back where you started).
I have no trouble getting the ship and objects to wrap, but the background doesn't show up until the viewport itself passes an edge of the gameworld. Is it possible to make the background surface "wrap" around?
I'm sorry if I'm not being very articulate. It seems like a simple problem and tons of games do it, but I haven't had any luck finding an answer. I have some idea about how to do it by tiling the background, but it would be nice if I could just tell the surface to wrap.
I don't think so, I have an idea though. I'm guessing your background wraps horizontally and always to the right, then you could attach part of the beginning to the end of the background.
Example, if you have a 10,000px background and your viewport is 1000px, attach the first 1000px to the end of the background, so you'll have a 11,000px background. Then when the vieport reaches the end of the background, you just move it to the 0px position and continue moving right.
I was monkeying around with something similar to what you described that may be of use. I decided to try using a single map class which contained all of my Tiles, and I wanted only part of it loaded into memory at once so I broke it up into Sectors (32x32 tiles). I limited it to only having 3x3 Sectors loaded at once. As my map scrolled to an edge, it would unload the Sectors on the other side and load in new ones.
My Map class would have a Rect of all loaded Sectors, and my camera would have a Rect of where it was located. Each tick I would use those two Rects to find what part of the Map I should blit, and if I should load in new Sectors. Once you start to change what Sectors are loaded, you have to shift
Each sector had the following attributes:
1. Its Coordinate, with (0, 0) being the topleft most possible Sector in the world.
2. Its Relative Sector Coordinate, with (0, 0) being the topleft most loaded sector, and (2,2) the bottom right most if 3x3 were loaded.
3. A Rect that held the area of the Sector
4. A bool to indicate of the Sector was fully loaded
Each game tick would check if the bool to see if Sector was fully loaded, and if not, call next on a generator that would blit X tiles onto the Map surface. I
The entire Surface
Each update would unload, load, or update and existing Sector
When an existing Sector was updated, it would shift
It would unload Sectors on update, and then create the new ones required. After being created, each Sector would start a generator that would blit X amount of tiles per update
Thanks everyone for the suggestions. I ended up doing something a little different from the answers provided. Essentially, I made subsurfaces of the main surface and used them as buffers, displaying them as appropriate whenever the viewport included coordinates outside the world. Because the scrolling is omnidirectional, I needed to use 8 buffers, one for each side and all four corners. My solution may not be the most elegant, but it seems to work well, with no noticeable performance drop.