TKinter处理多个监视器和图像显示

2024-06-26 13:24:23 发布

您现在位置:Python中文网/ 问答频道 /正文

我有功能代码,但有一些事情我想改变它,但不知道如何,所以我想在这里问一下。我的代码如下:

import numpy as np
from PIL import Image
import matplotlib.pyplot as plt
import tkinter as tk
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg


#Define the target, source and output arrays. Source has to be completely white otherwise it kills everything
def initialize(x,y):
    xarr = np.zeros(x)
    yarr = np.zeros(y)
    target = np.meshgrid(xarr,yarr)
    target = target[0]
    source = np.meshgrid(xarr,yarr)
    source = source[0]
    output = np.meshgrid(xarr,yarr)
    output = output[0]
    for i in range(x):
        for n in range(y):
            source[n][i] = 1
    return target, source, output

# creates trap between XTrapMin-XTrapMax and YTrapMin-YTrapMax on Array
def trap(xtmi,xtma,xs,ytmi,ytma,ys,array):
    for i in range(xs):
        if xtmi < i < xtma:
            for n in range(ys):
                if ytmi < n < ytma:
                    array[n][i] = 255
    return

#Returns the amplitude of a complex number
def Amplitude(x):
    if isinstance(x, complex):
        return np.sqrt(x.real**2+x.imag**2)
    else:
        return np.abs(x)

#Returns the phase of a complex number
def Phase(z):
        return np.angle(z)

#Main GS algorithm implementation using numpy FFT package
#performs the GS algorithm to obtain a phase distribution for the plane, Source
#such that its Fourier transform would have the amplitude distribution of the plane, Target.
def GS(target,source):
    A = np.fft.ifft2(target)
    for i in range(5):
        B = Amplitude(source) * np.exp(1j * Phase(A))
        C = np.fft.fft2(B)
        D = Amplitude(target) * np.exp(1j * Phase(C))
        A = np.fft.ifft2(D)
    output = Phase(A)
    return output

#Make array into PIL Image
def mkPIL(array):
    im = Image.fromarray(np.uint8(array))
    return im

def up():
    global ytmi
    global ytma
    ytmi -= 10
    ytma -= 10
    return 

def down():
    global ytmi
    global ytma
    ytmi += 10
    ytma += 10
    return

def right():
    global xtmi
    global xtma
    xtmi += 10
    xtma += 10
    return

def left():
    global xtmi
    global xtma
    xtmi -= 10
    xtma -= 10
    return

xtmi = 125
xtma = 130
xs = 1024
ytmi = 0
ytma = 5
ys = 768


root = tk.Tk()
root.attributes('-fullscreen', True)
def main():
    app = Lower(root)
    root.mainloop()

class Lower:
    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master).pack()
        self.displayimg = tk.Button(self.frame, text = 'Display', width = 25, command = self.plot)
        self.displayimg.pack()
        self.makewidg()
    def makewidg(self):
        self.fig = plt.figure(figsize=(100,100), frameon=False)  #changing figsize doesnt cange the size of the plot display
        self.fig.subplots_adjust(left=0, right=1, top=1, bottom=0)
        self.fig.tight_layout()
        self.ax = self.fig.add_subplot(111)
        self.ax.set_yticklabels([])                        
        self.ax.set_xticklabels([])
        self.canvas = FigureCanvasTkAgg(self.fig, master=self.master)
        self.canvas.get_tk_widget().pack(expand=True)
        self.canvas.figure.tight_layout()
        self.canvas.draw()
        self.new_window()
    def new_window(self):
        self.newWindow = tk.Toplevel()
        self.app = Display(self.newWindow)
    def plot(self): 
        global xtmi, xtma, xs, ytmi, ytma, ys, i
        target,source,output=initialize(xs,ys)
        trap(xtmi,xtma,xs,ytmi,ytma,ys,target)
        output = GS(target,source)
        self.ax.imshow(output, cmap='gray')
        self.ax.set_yticklabels([])                        
        self.ax.set_xticklabels([])
        self.canvas.draw()
        self.ax.clear()

    def kill(self): 
        root.destroy()

class Display:

    def __init__(self, master):
        self.master = master
        self.frame = tk.Frame(self.master)
        self.frame.pack()
        self.up = tk.Button(self.frame, text = 'Up', width = 25, command = up)
        self.up.pack()
        self.down = tk.Button(self.frame, text = 'Down', width = 25, command = down)
        self.down.pack()
        self.right = tk.Button(self.frame, text =  'Right', width = 25, command = right)
        self.right.pack()
        self.left = tk.Button(self.frame, text = 'Left', width = 25, command = left)
        self.left.pack()
        self.kill = tk.Button(self.frame, text = 'Kill', width = 25, command = self.kill)
        self.kill.pack()
    def kill(self): 
        root.destroy()
main()

当前,显示类下方的按钮displayimg显示在图像上方,是否有一种方法可以使显示类上的显示按钮仍能在较低屏幕上操作图像?另外,我打算在一个单独的显示器上显示Lower打开的窗口,但不能拖动它,因为它是全屏的,有没有办法让我在第二个显示器上看到它


我尝试这样做:

self.displayimg = tk.Button(self.top, text = 'Display', width = 25, command = Lower.plot(Lower)) 
self.displayimg.pack() 

但当我得到一个错误代码时,我想这会导致一个错误引用

AttributeError: type object 'Lower' has no attribute 'ax'


Tags: theselfmastersourcetargetoutputreturndef
1条回答
网友
1楼 · 发布于 2024-06-26 13:24:23

调用Lower.plot

您正在使用Lower.plot作为按钮命令。它需要一个参数self,它必须是Lower的实例-因此Lower.plot(Lower)正在传递一个类,该类需要一个实例。相反,您需要使用已创建的应用程序实例,并调用app.plot()。参数self自动成为实例本身,这是python中OOP的基础。在实例上调用该方法将self作为第一个参数传递,因此调用中缺少该参数。调用Lower.plot(...)就是调用类Lower上的方法,因此没有实例,您必须提供自己的实例。在这种情况下,我避免在没有实例的情况下调用方法,而是使用app实例

显示按钮的命令

您的按钮创建类似于: self.displayimg = tk.Button(self.top, text = 'Display', width = 25, command = app.plot) 如果需要将其他参数传递给plot,则需要延迟函数调用,以便在单击而不是创建按钮时调用。您可以使用lambda : app.plot("red", 10, whatever)生成一个不带参数的无名函数,当调用该函数时,它将继续使用给定的参数调用app.plot

定位窗口

您可以使用wm_geometry控制应用程序窗口的位置:

app.wm_geometry("200x200+100+500")

将使应用程序窗口以200px乘以200px的速度显示,位于原点左侧100px和下方500px处,在windows计算机上,这是主监视器的左上角。您可以保持宽度和高度相同,只需使用eg移动窗口

app.wm_geometry("+100+500")

您可以使用更多的脚本来构建字符串+{xpos}+{ypos},使用与桌面布局匹配的任何值

相关问题 更多 >