Summary:
I Am programing a program that draws many shapes(Polygon, We have at least 3 points in each object if not more). Each polygon is an object. Right now am adding a feature so the user can select objects and move them ( With mouse selection like on the desktop selecting icons).
Using: Python 3.7, PyQt5, QPixmap
How I thought to add that feature: After drawing the objects, if the user starts selecting objects:
-
First the code will take all objects that the user has drawn and loop them and see which of them are in the selection area and add them to the selected list.
-
Second, If the user clicked on the selection area => Held those objects in the selected list and start moving them (Here it will loop each 1 pixel the user moves his mouse, Too many processes here)
The issue is: I have many loops in my code, And I don't think it is really effective way to do it like this. So am asking if there is any other option I can get the same results but with better code like design pattern or something, I don't know, Did I done it wrong?
The code:
def inside_selection(obj, begin_point, destination_point):
# Calculate the other two rectangle's point
p2 = Point(begin_point[0], destination_point[1], 0)
p4 = Point(destination_point[0], begin_point[1], 0)
rect_points = [begin_point, p2, destination_point, p4]
rect = shp.Polygon(rect_points)
if isinstance(obj, Point):
point = obj
result = rect.contains(shp.Point(point[0], point[1], 0))
return result
else:
points = obj.get_points() # each object has many points it is Polygon
for point in points:
result = rect.contains(shp.Point(point[0], point[1], 0))
if result is True:
return result
class HandTool:
def __init__(self):
self.begin, self.destination = None, None # two corner of the rectangle of selection
self.held_objects = None # the objects holding by the user to move them
self.selected_objects = [] # store all objects inside the selection area
self.selecting = False # for drawing a selection area
self.copy_points = None
self.first_click = None
def mouse_click(self, event):
point = Point(event.x(), event.y(), 0) # Cordinatins where user clicked
# check if there are a selected objects
# And check if the clicked was on the selection area so the user want to move an objects
if self.selected_objects and inside_selection(point, self.begin, self.destination):
# ISSUE 1.0
# make a copy so after the user moved them it won't change the original corrdinate
self.held_objects = self.selected_objects.copy()
# Loop 1
for obj in self.held_objects:
pass # some code here to make the original hidden while moving it like(Drag Drop)
self.canvas.setMouseTracking(True)
# else the click was outside the selection area so the user won't move any selected objects
else:
self.begin = point
self.destination = self.begin
self.selecting = True
self.selected_objects = []
self.canvas.update_pixmap()
def mouse_move(self, event):
# if the user moving many object
if self.held_objects is not None:
for obj in self.held_objects:
self.move_held_objects(e)
self.canvas.update_pixmap()
def mouse_release(self, event):
# After user draw a selection and both begin and destination are not None, detemin which object(shape like points...etc)
# is inside this selection
if self.begin is not None and self.destination is not None:
for obj in all_objects: # all objects in the widget
if inside_selection(obj, self.begin, self.destination): # loop for all object and see if inside or not
self.selected_objects.append(obj) # if True then it is inside the selection area so add it to list
if obj.is_polygon():
# Make the selected objects visiable to user by changeing points's color to red
for point_id, _ in enumerate(obj.get_points(), 0):
self.zkpainter.draw_ellipse(obj.get_points()[point_id], 5, brush=QBrush(Qt.red))
if self.held_objects:
for obj in self.held_objects:
pass # Some code to make the new changes of the objects on the view
self.selected_objects = []
self.canvas.update_pixmap()
self.held_objects = None
self.selecting = False
def move_held_objects(self, event):
# Calculate how much the mouse moved since the user clicked and moving the objects
diff_x, diff_y = event.x() - self.first_click[0], event.y() - self.first_click[1]
for obj_id, obj in enumerate(self.held_objects):
if obj.is_polygon():
old_position = self.selected_objects[obj_id].get_points()
for point_id, _ in enumerate(obj.get_points()):
obj.get_points()[point_id][1] = old_position[point_id][1] + diff_y
obj.get_points()[point_id][0] = old_position[point_id][0] + diff_x
Aucun commentaire:
Enregistrer un commentaire