如何在python窗口应用程序中实现拖动功能(或缩放)?

时间:2015-03-26 10:31:14

标签: python turtle-graphics

我正在使用python中的乌龟图形做一些简单的分形图,并且遇到了乌龟超出应用程序框架的情况。 我希望能够在窗口中拖动视图,以便我可以将其放在我正在绘制的分形的不同部分上,或者放大或缩小以操纵视图。 < / p>

Python有一个模块吗?我对python相对较新,因为我主要使用Java编程,并且可以想到许多方法来处理Java和JFrame等。我对一个简单的python实现的研究没有结果:(我不想重新发明轮子如果有一个简单的解决方案可用〜虽然所有方法都很受欢迎。如果我错过了本网站上的另一个回复我的问题的帖子,请发表评论。

这是我感兴趣的任何人的分形码。

import turtle

t = turtle.Turtle()
t.color("white")
t.backward(450)
t.color("red")

def f2(length, depth):
    if depth == 0:
        t.forward(length)
    else:
        f2(length/2, depth -1)
        t.left(135)
        f2(length/8, depth -1)
        t.right(90)
        f2(length/8, depth -1)
        t.right(90)
        f2(length/8, depth -1)
        t.right(90)
        f2(length/8, depth -1)
        t.left(135)
        f2(length/2, depth -1)


f2(400, 4)

2 个答案:

答案 0 :(得分:1)

有几种方法你可以做到这一点,我有一段时间需要,不幸的是我不认为有一个非常简单的方法。但您可以使用:

显式设置画布的大小(如果大于显示的大小,则添加滚动条)
screen.screensize(width, height)

这通常作用于乌龟屏幕而不是乌龟自己,所以要获得你需要调用的屏幕:

t.getscreen()

有一种更复杂但更有能力的方法,你将乌龟子类化以跟踪它的边界框(每个轴上移动的最远点),然后根据它更新屏幕大小,但它很多如果被问到,我会发布更多信息。

编辑:添加子类化方法的细节 首先我们将乌龟子类化,使其具有一个名为bbox的属性,这是一个每次移动乌龟时都会更新的列表。

class MyTurtle(turtle.RawTurtle): # here we subclass the turtle to allow us to call statusbar updates after each movement
    def __init__(self, canvas):
        turtle.RawTurtle.__init__(self, canvas)
        self.bbox = [0,0,0,0]

    def _update_bbox(self): # keep a record of the furthers points visited
        pos = self.position()
        if pos[0] < self.bbox[0]:
            self.bbox[0] = pos[0]
        elif pos[0] > self.bbox[2]:
            self.bbox[2] = pos[0]
        if pos[1] < self.bbox[1]:
            self.bbox[1] = pos[1]
        elif pos[1] > self.bbox[3]:
            self.bbox[3] = pos[1]

    def forward(self, *args):
        turtle.RawTurtle.forward(self, *args)
        self._update_bbox()

    def backward(self, *args):
        turtle.RawTurtle.backward(self, *args)
        self._update_bbox()

    def right(self, *args):
        turtle.RawTurtle.right(self, *args)
        self._update_bbox()

    def left(self, *args):
        turtle.RawTurtle.left(self, *args)
        self._update_bbox()

    def goto(self, *args):
        turtle.RawTurtle.goto(self, *args)
        self._update_bbox()

    def setx(self, *args):
        turtle.RawTurtle.setx(self, *args)
        self._update_bbox()

    def sety(self, *args):
        turtle.RawTurtle.sety(self, *args)
        self._update_bbox()

    def setheading(self, *args):
        turtle.RawTurtle.setheading(self, *args)
        self._update_bbox()

    def home(self, *args):
        turtle.RawTurtle.home(self, *args)
        self._update_bbox()

然后我们为乌龟创建一个画布:

cv = turtle.ScrolledCanvas(root)

然后我们把那个画布变成了一个海龟画面:

screen = turtle.TurtleScreen(cv)

我们在屏幕上创建了一只乌龟:

turt = MyTurtle(screen)

现在乌龟可以用作普通乌龟(移动,颜色,形状,速度等) 如果乌龟超出了屏幕的范围,你可以打电话:

min_x, min_y, max_x, max_y = turt.bbox # get the furthest points the turtle has been
width = max((0-min_x),(max_x)) * 2 + 100 # work out what the maximum distance from 0,0 is for each axis
height = max((0-min_y),(max_y)) * 2 + 100 # the 100 here gives us some padding between the edge and whats drawn
screen.screensize(width, height)

请注意,上面的代码重新调整大小与屏幕方法所允许的内容相同,但是如果您深入研究并将bbox应用于画布本身,则可以使其仅在画布上的项目周围进行调整。

答案 1 :(得分:1)

这在我的编程课程中出现了很多次。我的解决方案也有点复杂,但它正确地为我添加了滚动条(不幸的是,随着屏幕尺寸的增大,它们似乎不会自动添加),而且我不需要跟踪边界框自己。

以下是设置:

import turtle
import Tkinter

root = Tkinter.Tk()
START_WIDTH = 700 
START_HEIGHT = 700 

frame = Tkinter.Frame(root, width=START_WIDTH, height=START_HEIGHT)
frame.grid_rowconfigure(0, weight=1)
frame.grid_columnconfigure(0, weight=1)

xscrollbar = Tkinter.Scrollbar(frame, orient=Tkinter.HORIZONTAL)
xscrollbar.grid(row=1, column=0, sticky=Tkinter.E+Tkinter.W)

yscrollbar = Tkinter.Scrollbar(frame, orient=Tkinter.VERTICAL)
yscrollbar.grid(row=0, column=1, sticky=Tkinter.N+Tkinter.S)

canvas = Tkinter.Canvas(frame, width=START_WIDTH, height=START_HEIGHT,
                        scrollregion=(0, 0, START_WIDTH, START_HEIGHT),
                        xscrollcommand=xscrollbar.set,
                        yscrollcommand=yscrollbar.set)

canvas.grid(row=0, column=0, sticky=Tkinter.N+Tkinter.S+Tkinter.E+Tkinter.W)

xscrollbar.config(command=canvas.xview)
yscrollbar.config(command=canvas.yview)

frame.pack()

turt = turtle.RawTurtle(canvas)

现在您可以使用turt,就像您创建的任何其他龟对象一样。每次要确保可以滚动到已绘制的所有内容时,请运行

canvas.config(scrollregion=canvas.bbox(Tkinter.ALL))

有关自定义画布和滚动条的文档,请参阅http://effbot.org/zone/tkinter-scrollbar-patterns.htmhttp://effbot.org/tkinterbook/canvas.htm