【问题标题】:Python Tkinter on Debian Beaglebone: lost font styling when changed directory nameDebian Beaglebone 上的 Python Tkinter:更改目录名称时丢失字体样式
【发布时间】:2023-05-04 07:11:02
【问题描述】:

我已经在 BeagleBone Black (Debian Jessie) 上安装了非系统字体,并且一直在通过 Tkinter 和 tkFont 使用 python 2.7 脚本创建的 GUI 中使用它们。当我更改存储文件的目录名称时,这些字体不再出现在我的 python 脚本 GUI 中!

我将字体安装到 /usr/shared/fonts 中,它们当然仍然存在,但不知何故我失去了与脚本中字体的连接。

我运行fc-cache -fv 并重新启动。我用

运行了一个简短的脚本
list( tkFont.families() )

在其中,我想使用的任何字体都会出现在列表中。

仍然在 GUI 中显示系统字体。

怎么可能?这是我的代码:

#!/usr/bin/python

import time
import threading
import Queue

import Tkinter as tk
import tkFont

try:
    import alsaaudio as aa
    import audioop
    import Adafruit_BBIO.GPIO as GPIO
    debug = False
except ImportError:
    # To enable simple testing on systems without alsa/gpio
    import mock

    aa = mock.MagicMock()
    aa.PCM().read.return_value = (1, '')

    audioop = mock.MagicMock()
    audioop.max.return_value = 5000

    GPIO = mock.MagicMock()

    import random
    GPIO.input.side_effect = lambda *a: random.randint(0, 5000) == 0

    debug = True

# layout ########################################################

BACKGROUND_COLOR = '#000000'

TEXTBOX_WIDTH = 1920

# vertical alignment of text in percentages from top

V_ALIGN_L1 = .16
V_ALIGN_L2 = .28
V_ALIGN_HEADER = .52
V_ALIGN_SCORE = .68
V_ALIGN_TILT = .50
V_ALIGN_AGAIN = .68

# type ##########################################################

TYPEFACE_L1 = 'Avenir Next Demi Bold'
TYPEFACE_L2 = 'Avenir Next Bold'
TYPEFACE_HEADER = 'Avenir Next Bold'
TYPEFACE_SCORE = 'Avenir Next Demi Bold'
TYPEFACE_TILT = 'Avenir Next Bold'
TYPEFACE_AGAIN = 'Avenir Next Bold'

WEIGHT_L1 = tkFont.NORMAL
WEIGHT_L2 = tkFont.BOLD
WEIGHT_HEADER = tkFont.BOLD
WEIGHT_SCORE = tkFont.NORMAL
WEIGHT_TILT = tkFont.BOLD
WEIGHT_AGAIN = tkFont.BOLD

FONT_SIZE_L1 = 56
FONT_SIZE_L2 = 56
FONT_SIZE_HEADER = 76
FONT_SIZE_SCORE = 168
FONT_SIZE_TILT = 114
FONT_SIZE_AGAIN = 76

LINE_HEIGHT_L1 = -5
LINE_HEIGHT_L2 = -5
LINE_HEIGHT_HEADER = -10
LINE_HEIGHT_SCORE = -20
LINE_HEIGHT_TILT = -20
LINE_HEIGHT_AGAIN = -1

TEXT_COLOR_HIGHLIGHT = '#FFFFFF'
TEXT_COLOR_BODY = '#92C73D'

# text ###########################################################

L1 = 'Try to beat your own score.'
L2 = 'The lowest score wins!'
HEADER_MESSAGE = 'Your Score:'
TILT_MESSAGE = 'Too loud!'
TRY_AGAIN = 'Start again!'

# audio collection configuration ##################################

BUTTON_PIN = 'P8_12'

DEVICE = 'hw:1'  # hardware sound card index
CHANNELS = 2
SAMPLE_RATE = 44100  # Hz
PERIOD = 256  # Frames
FORMAT = aa.PCM_FORMAT_S16_LE  # Sound format

NOISE_THRESHOLD = 0  # to eliminate small noises, scale of 0 - 7
TILT_THRESHOLD = 100.0 # upper limit of score before tilt state
SCALAR = 4680 # normalizes score, found by trial and error
UPDATE_TIME = 100 # ms

# start script ###################################################

class Display(object):

    def __init__(self, parent, queue, stop_event):
        self.parent = parent
        self.queue = queue
        self.stop_event = stop_event
        self.tilt_event = threading.Event()

        self._geom = '200x200+0+0'
        parent.geometry("{0}x{1}+0+0".format(
            parent.winfo_screenwidth(), parent.winfo_screenheight()))
        parent.overrideredirect(1)

        parent.title(TITLE)
        parent.configure(background=BACKGROUND_COLOR)
        self.create_text()
        self.process_queue()

        self.audio_thread = threading.Thread(target=self.setup_audio)
        self.audio_thread.start()

    def __delete__(self, instance):
        instance.stop_event.set()

    def create_text(self):
        message_kwargs = dict(
            bg=BACKGROUND_COLOR,
            width=TEXTBOX_WIDTH,
            justify='c',
        )

        self.message_L1 = tk.Message(
            self.parent,
            text=L1,
            fg=TEXT_COLOR_HIGHLIGHT,
            font=(TYPEFACE_HEADER, FONT_SIZE_L1, WEIGHT_L1),
            pady=LINE_HEIGHT_L1,
            **message_kwargs)

        self.message_L2 = tk.Message(
            self.parent,
            text=L2,
            fg=TEXT_COLOR_HIGHLIGHT,
            font=(TYPEFACE_HEADER, FONT_SIZE_L2, WEIGHT_L2),
            pady=LINE_HEIGHT_L2,
            **message_kwargs)

        self.message_score_header = tk.Message(
            self.parent,
            text=HEADER_MESSAGE,
            fg=TEXT_COLOR_BODY,
            font=(TYPEFACE_HEADER, FONT_SIZE_HEADER, WEIGHT_HEADER),
            pady=LINE_HEIGHT_HEADER,
            **message_kwargs)
        self.message_score = tk.Message(
            self.parent,
            text='0.0',
            fg=TEXT_COLOR_HIGHLIGHT,
            font=(TYPEFACE_SCORE, FONT_SIZE_SCORE, WEIGHT_SCORE),
            pady=LINE_HEIGHT_SCORE,
            **message_kwargs)

        self.message_L1.place(relx=.5, rely=V_ALIGN_L1, anchor='c')
        self.message_L2.place(relx=.5, rely=V_ALIGN_L2, anchor='c')
        self.message_score_header.place(relx=V_ALIGN_HEADER, rely=.5, anchor='c')
        self.message_score.place(relx=.5, rely=V_ALIGN_SCORE, anchor='c')

    def process_queue(self):
        text = None
        while not self.queue.empty():
            text = self.queue.get_nowait()

        if text:
            self.message_score_header.configure(text=HEADER_MESSAGE)
            self.message_score.configure(text=text)
        elif self.tilt_event.is_set():
            self.message_L1.configure(text="")
            self.message_L2.configure(text="")
            self.message_score_header.configure(text=TILT_MESSAGE, fg=TEXT_COLOR_HIGHLIGHT, font=(TYPEFACE_TILT, FONT_SIZE_TILT, WEIGHT_TILT), pady=LINE_HEIGHT_TILT)
            self.message_score.configure(text=TRY_AGAIN, fg=TEXT_COLOR_BODY, font=(TYPEFACE_AGAIN, FONT_SIZE_AGAIN, WEIGHT_AGAIN), pady=LINE_HEIGHT_AGAIN)
            self.message_score.place(relx=.75, rely=V_ALIGN_AGAIN, anchor='c')

        self.parent.after(UPDATE_TIME, self.process_queue)

    def setup_audio(self):
        data_in = aa.PCM(aa.PCM_CAPTURE, aa.PCM_NONBLOCK, DEVICE)
        data_in.setchannels(2)
        data_in.setrate(SAMPLE_RATE)
        data_in.setformat(FORMAT)

        data_in.setperiodsize(PERIOD)

        score = 0
        running = False

        while not self.stop_event.is_set():
            # Sleep a very short time to prevent the thread from locking up
            time.sleep(0.001)

            if GPIO.input(BUTTON_PIN):
                self.tilt_event.clear()
                score = 0
                if not running:
                    self.message_L1.configure(text=L1)
                    self.message_L2.configure(text=L2)
                    self.message_score_header.configure(text=HEADER_MESSAGE, fg=TEXT_COLOR_BODY, font=(TYPEFACE_HEADER, FONT_SIZE_HEADER, WEIGHT_HEADER), pady=LINE_HEIGHT_HEADER)
                    self.message_score.configure(text='0.0', fg=TEXT_COLOR_HIGHLIGHT, font=(TYPEFACE_SCORE, FONT_SIZE_SCORE, WEIGHT_SCORE), pady=LINE_HEIGHT_SCORE)
                    self.message_score.place(relx=.5, rely=V_ALIGN_SCORE, anchor='c')

                    running = True
                self.queue.put('0.0')
            elif not running:
                # Not running yet, keep waiting
                continue

            # Read data from device
            l, data = data_in.read()
            if l and not self.tilt_event.is_set():
                # catch frame error
                try:
                    max = audioop.max(data, CHANNELS)
                    scaled_max = max // SCALAR

                    if scaled_max <= NOISE_THRESHOLD:
                        # Too quiet, ignore
                        continue

                    score += scaled_max / 10.0

                    if score > TILT_THRESHOLD:
                        self.tilt_event.set()
                        running = False
                    else:
                        self.queue.put(str(score))

                except audioop.error, e:
                    if e.message != "not a whole number of frames":
                        raise e


def main():
    GPIO.setup(BUTTON_PIN, GPIO.IN)
    stop_event = threading.Event()
    window = None

    try:
        root = tk.Tk()
        queue = Queue.Queue()
        window = Display(root, queue, stop_event)

        # Force the window to the foreground
        root.attributes('-topmost', True)
        if debug:
            root.maxsize(1920, 1200)

        root.mainloop()
    finally:
        stop_event.set()
        if window:
            window.audio_thread.join()
        del window


if __name__ == '__main__':
    main()

运行脚本时没有错误消息。

编辑:还值得一提的是字体大小和粗细都在起作用,而不是字体。

【问题讨论】:

    标签: python tkinter beagleboneblack


    【解决方案1】:

    我认为您缺少 Font() 构造:

    self.message_score.configure(
        text=TRY_AGAIN,
        fg=TEXT_COLOR_BODY,
        font=(TYPEFACE_AGAIN, FONT_SIZE_AGAIN, WEIGHT_AGAIN),
        pady=LINE_HEIGHT_AGAIN)
    

    可能是:

    self.message_score.configure(
        text=TRY_AGAIN,
        fg=TEXT_COLOR_BODY,
        font=tkFont.Font(TYPEFACE_AGAIN, FONT_SIZE_AGAIN, WEIGHT_AGAIN),
        pady=LINE_HEIGHT_AGAIN)
    

    完整版:

    #!/usr/bin/python
    
    import time
    import threading
    import Queue
    
    import Tkinter as tk
    import tkFont
    
    try:
        import alsaaudio as aa
        import audioop
        import Adafruit_BBIO.GPIO as GPIO
        debug = False
    except ImportError:
        # To enable simple testing on systems without alsa/gpio
        import mock
    
        aa = mock.MagicMock()
        aa.PCM().read.return_value = (1, '')
    
        audioop = mock.MagicMock()
        audioop.max.return_value = 5000
    
        GPIO = mock.MagicMock()
    
        import random
        GPIO.input.side_effect = lambda *a: random.randint(0, 5000) == 0
    
        debug = True
    
    # layout ########################################################
    
    BACKGROUND_COLOR = '#000000'
    
    TEXTBOX_WIDTH = 1920
    
    # vertical alignment of text in percentages from top
    
    V_ALIGN_L1 = .16
    V_ALIGN_L2 = .28
    V_ALIGN_HEADER = .52
    V_ALIGN_SCORE = .68
    V_ALIGN_TILT = .50
    V_ALIGN_AGAIN = .68
    
    # type ##########################################################
    
    TYPEFACE_L1 = 'Avenir Next Demi Bold'
    TYPEFACE_L2 = 'Avenir Next Bold'
    TYPEFACE_HEADER = 'Avenir Next Bold'
    TYPEFACE_SCORE = 'Avenir Next Demi Bold'
    TYPEFACE_TILT = 'Avenir Next Bold'
    TYPEFACE_AGAIN = 'Avenir Next Bold'
    
    WEIGHT_L1 = tkFont.NORMAL
    WEIGHT_L2 = tkFont.BOLD
    WEIGHT_HEADER = tkFont.BOLD
    WEIGHT_SCORE = tkFont.NORMAL
    WEIGHT_TILT = tkFont.BOLD
    WEIGHT_AGAIN = tkFont.BOLD
    
    FONT_SIZE_L1 = 56
    FONT_SIZE_L2 = 56
    FONT_SIZE_HEADER = 76
    FONT_SIZE_SCORE = 168
    FONT_SIZE_TILT = 114
    FONT_SIZE_AGAIN = 76
    
    LINE_HEIGHT_L1 = -5
    LINE_HEIGHT_L2 = -5
    LINE_HEIGHT_HEADER = -10
    LINE_HEIGHT_SCORE = -20
    LINE_HEIGHT_TILT = -20
    LINE_HEIGHT_AGAIN = -1
    
    TEXT_COLOR_HIGHLIGHT = '#FFFFFF'
    TEXT_COLOR_BODY = '#92C73D'
    
    # text ###########################################################
    
    L1 = 'Try to beat your own score.'
    L2 = 'The lowest score wins!'
    HEADER_MESSAGE = 'Your Score:'
    TILT_MESSAGE = 'Too loud!'
    TRY_AGAIN = 'Start again!'
    
    # audio collection configuration ##################################
    
    BUTTON_PIN = 'P8_12'
    
    DEVICE = 'hw:1'  # hardware sound card index
    CHANNELS = 2
    SAMPLE_RATE = 44100  # Hz
    PERIOD = 256  # Frames
    FORMAT = aa.PCM_FORMAT_S16_LE  # Sound format
    
    NOISE_THRESHOLD = 0  # to eliminate small noises, scale of 0 - 7
    TILT_THRESHOLD = 100.0 # upper limit of score before tilt state
    SCALAR = 4680 # normalizes score, found by trial and error
    UPDATE_TIME = 100 # ms
    
    # start script ###################################################
    
    class Display(object):
    
        def __init__(self, parent, queue, stop_event):
            self.parent = parent
            self.queue = queue
            self.stop_event = stop_event
            self.tilt_event = threading.Event()
    
            self._geom = '200x200+0+0'
            parent.geometry("{0}x{1}+0+0".format(
                parent.winfo_screenwidth(), parent.winfo_screenheight()))
            parent.overrideredirect(1)
    
            parent.title(TITLE)
            parent.configure(background=BACKGROUND_COLOR)
            self.create_text()
            self.process_queue()
    
            self.audio_thread = threading.Thread(target=self.setup_audio)
            self.audio_thread.start()
    
        def __delete__(self, instance):
            instance.stop_event.set()
    
        def create_text(self):
            message_kwargs = dict(
                bg=BACKGROUND_COLOR,
                width=TEXTBOX_WIDTH,
                justify='c',
            )
    
            self.message_L1 = tk.Message(
                self.parent,
                text=L1,
                fg=TEXT_COLOR_HIGHLIGHT,
                font=tkFont.Font(TYPEFACE_HEADER, FONT_SIZE_L1, WEIGHT_L1),
                pady=LINE_HEIGHT_L1,
                **message_kwargs)
    
            self.message_L2 = tk.Message(
                self.parent,
                text=L2,
                fg=TEXT_COLOR_HIGHLIGHT,
                font=tkFont.Font(TYPEFACE_HEADER, FONT_SIZE_L2, WEIGHT_L2),
                pady=LINE_HEIGHT_L2,
                **message_kwargs)
    
            self.message_score_header = tk.Message(
                self.parent,
                text=HEADER_MESSAGE,
                fg=TEXT_COLOR_BODY,
                font=tkFont.Font(TYPEFACE_HEADER, FONT_SIZE_HEADER, WEIGHT_HEADER),
                pady=LINE_HEIGHT_HEADER,
                **message_kwargs)
            self.message_score = tk.Message(
                self.parent,
                text='0.0',
                fg=TEXT_COLOR_HIGHLIGHT,
                font=tkFont.Font(TYPEFACE_SCORE, FONT_SIZE_SCORE, WEIGHT_SCORE),
                pady=LINE_HEIGHT_SCORE,
                **message_kwargs)
    
            self.message_L1.place(relx=.5, rely=V_ALIGN_L1, anchor='c')
            self.message_L2.place(relx=.5, rely=V_ALIGN_L2, anchor='c')
            self.message_score_header.place(relx=V_ALIGN_HEADER, rely=.5, anchor='c')
            self.message_score.place(relx=.5, rely=V_ALIGN_SCORE, anchor='c')
    
        def process_queue(self):
            text = None
            while not self.queue.empty():
                text = self.queue.get_nowait()
    
            if text:
                self.message_score_header.configure(text=HEADER_MESSAGE)
                self.message_score.configure(text=text)
            elif self.tilt_event.is_set():
                self.message_L1.configure(text="")
                self.message_L2.configure(text="")
                self.message_score_header.configure(
                    text=TILT_MESSAGE,
                    fg=TEXT_COLOR_HIGHLIGHT,
                    font=tkFont.Font(
                        TYPEFACE_TILT,
                        FONT_SIZE_TILT,
                        WEIGHT_TILT,
                    ),
                    pady=LINE_HEIGHT_TILT)
                self.message_score.configure(
                    text=TRY_AGAIN,
                    fg=TEXT_COLOR_BODY,
                    font=tkFont.Font(
                        TYPEFACE_AGAIN,
                        FONT_SIZE_AGAIN,
                        WEIGHT_AGAIN,
                    ),
                    pady=LINE_HEIGHT_AGAIN)
                self.message_score.place(relx=.75, rely=V_ALIGN_AGAIN, anchor='c')
    
            self.parent.after(UPDATE_TIME, self.process_queue)
    
        def setup_audio(self):
            data_in = aa.PCM(aa.PCM_CAPTURE, aa.PCM_NONBLOCK, DEVICE)
            data_in.setchannels(2)
            data_in.setrate(SAMPLE_RATE)
            data_in.setformat(FORMAT)
    
            data_in.setperiodsize(PERIOD)
    
            score = 0
            running = False
    
            while not self.stop_event.is_set():
                # Sleep a very short time to prevent the thread from locking up
                time.sleep(0.001)
    
                if GPIO.input(BUTTON_PIN):
                    self.tilt_event.clear()
                    score = 0
                    if not running:
                        self.message_L1.configure(text=L1)
                        self.message_L2.configure(text=L2)
                        self.message_score_header.configure(
                            text=HEADER_MESSAGE,
                            fg=TEXT_COLOR_BODY,
                            font=tkFont.Font(
                                TYPEFACE_HEADER,
                                FONT_SIZE_HEADER,
                                WEIGHT_HEADER,
                            ),
                            pady=LINE_HEIGHT_HEADER)
                        self.message_score.configure(
                            text='0.0',
                            fg=TEXT_COLOR_HIGHLIGHT,
                            font=tkFont.Font(
                                TYPEFACE_SCORE,
                                FONT_SIZE_SCORE,
                                WEIGHT_SCORE,
                            ),
                            pady=LINE_HEIGHT_SCORE)
                        self.message_score.place(
                            relx=.5,
                            rely=V_ALIGN_SCORE,
                            anchor='c')
    
                        running = True
                    self.queue.put('0.0')
                elif not running:
                    # Not running yet, keep waiting
                    continue
    
                # Read data from device
                l, data = data_in.read()
                if l and not self.tilt_event.is_set():
                    # catch frame error
                    try:
                        max = audioop.max(data, CHANNELS)
                        scaled_max = max // SCALAR
    
                        if scaled_max <= NOISE_THRESHOLD:
                            # Too quiet, ignore
                            continue
    
                        score += scaled_max / 10.0
    
                        if score > TILT_THRESHOLD:
                            self.tilt_event.set()
                            running = False
                        else:
                            self.queue.put(str(score))
    
                    except audioop.error, e:
                        if e.message != "not a whole number of frames":
                            raise e
    
    
    def main():
        GPIO.setup(BUTTON_PIN, GPIO.IN)
        stop_event = threading.Event()
        window = None
    
        try:
            root = tk.Tk()
            queue = Queue.Queue()
            window = Display(root, queue, stop_event)
    
            # Force the window to the foreground
            root.attributes('-topmost', True)
            if debug:
                root.maxsize(1920, 1200)
    
            root.mainloop()
        finally:
            stop_event.set()
            if window:
                window.audio_thread.join()
            del window
    
    
    if __name__ == '__main__':
        main()
    
    There are no error messages when I run the script.
    

    【讨论】: