Giao diện thiết bị đầu cuối Python

Python có sẵn nhiều khung giao diện người dùng đồ họa [GUI]. Hầu hết trong số họ đã rất trưởng thành với nguồn mở và hỗ trợ thương mại; . Trong mọi trường hợp, việc lựa chọn sử dụng thư viện nào phụ thuộc vào ba yếu tố

  1. Dịch vụ điện toán đám mây

    • Đám mây lai là gì?
    • sách điện tử. Hiện đại hóa CNTT của bạn với các dịch vụ đám mây được quản lý
    • Bắt đầu với Dịch vụ OpenShift của Red Hat trên AWS [ROSA]
    • sách điện tử. Chiến lược đám mây lai cho người mới bắt đầu
    • Dịch vụ đám mây là gì?

    Trưởng thành. Nó có ổn định và được cộng đồng hỗ trợ tốt không, và nó có tài liệu tốt không?
  2. Tích hợp với Python. Bạn có thể nghĩ rằng đây là một cách nói kỳ quặc, nhưng nó có thể đặt ra một rào cản gia nhập đáng kể đối với bộ công cụ [bạn không muốn cảm thấy mình đang viết GUI trong một trình biên dịch chương trình; xét cho cùng, đó là Python]
  3. Nó có hỗ trợ trường hợp sử dụng của bạn không? . [Tkinter rất nổi tiếng. ] Nếu GUI của bạn phức tạp hơn, thì wxPython có thể phù hợp hơn vì nó hỗ trợ nhiều tính năng

Một quản trị viên hệ thống giỏi nên biết cách tạo các ứng dụng thân thiện với người dùng. Bạn sẽ ngạc nhiên về mức độ mà họ có thể cải thiện năng suất của bạn và cả năng suất của người dùng của bạn

Bạn có rất nhiều khung để lựa chọn. Trong bài viết này, tôi sẽ cung cấp tổng quan về ba trong số chúng. Rich, Tkinter và DearPyGui

Một đường vòng nhanh chóng. Chuẩn bị môi trường của bạn

Nếu bạn muốn làm theo hướng dẫn ngắn này, hãy chuẩn bị môi trường của bạn bằng cách chạy

$ git clone //github.com/josevnz/rpm_query
$ cd rpm_query
$ python3 -m venv --system-site-packages ~/virtualenv/rpm_query
$ . ~/virtualenv/rpm_query/bin/activate
$ python3 setup.py build
$ cp reporter build/scripts-3.?

bạn tốt để đi

Hiển thị danh sách RPM được sắp xếp theo kích thước

Ứng dụng ví dụ này không phức tạp lắm. Nó sẽ hiển thị đầu ra sau độc đáo

$ ./rpmq_simple.py --limit 10
linux-firmware-20210818: 395,099,476
code-1.61.2: 303,882,220
brave-browser-1.31.87: 293,857,731
libreoffice-core-7.0.6.2: 287,370,064
thunderbird-91.1.0: 271,239,962
firefox-92.0: 266,349,777
glibc-all-langpacks-2.32: 227,552,812
mysql-workbench-community-8.0.23: 190,641,403
java-11-openjdk-headless-11.0.13.0.8: 179,469,639
iwl7260-firmware-25.30.13.0: 148,167,043

Nó cũng sẽ cho phép người dùng chạy lại truy vấn của họ trong khi ghi đè số lượng kết quả khớp và tên gói, cũng như sắp xếp chúng theo kích thước tính bằng byte

[ Đăng ký khóa học trực tuyến miễn phí Tổng quan về kỹ thuật của Red Hat Enterprise Linux. ]

Bây giờ mọi thứ đã được thiết lập, bạn có thể bắt đầu tạo một ứng dụng. Dưới đây là ba khuôn khổ để xem xét

1. Giàu có

Will McGugan đã viết một framework cực kỳ dễ sử dụng có tên là Rich. Nó không cung cấp nhiều tiện ích [một dự án chị em vẫn đang trong giai đoạn thử nghiệm có tên là Textual hướng đến thành phần nhiều hơn. Kiểm tra ví dụ về bảng này]

Cài đặt phong phú

Cài đặt khung Rich

$ pip install rich

Đây là mã từ tập lệnh Python của tôi trong Rich. Nó tạo ra một thanh tiến trình và kết quả trên một bảng rất đẹp

#!/usr/bin/env python
"""
# rpmq_rich.py - A simple CLI to query the sizes of RPM on your system
Author: Jose Vicente Nunez
"""
import argparse
import textwrap
from reporter import __is_valid_limit__
from reporter.rpm_query import QueryHelper
from rich.table import Table
from rich.progress import Progress

if __name__ == "__main__":

    parser = argparse.ArgumentParser[description=textwrap.dedent[__doc__]]
    parser.add_argument[
        "--limit",
        type=__is_valid_limit__,  # Custom limit validator
        action="store",
        default=QueryHelper.MAX_NUMBER_OF_RESULTS,
        help="By default results are unlimited but you can cap the results"
    ]
    parser.add_argument[
        "--name",
        type=str,
        action="store",
        help="You can filter by a package name."
    ]
    parser.add_argument[
        "--sort",
        action="store_false",
        help="Sorted results are enabled bu default, but you fan turn it off"
    ]
    args = parser.parse_args[]

    with QueryHelper[
            name=args.name,
            limit=args.limit,
            sorted_val=args.sort
    ] as rpm_query:
        rpm_table = Table[title="RPM package name and sizes"]
        rpm_table.add_column["Name", justify="right", style="cyan", no_wrap=True]
        rpm_table.add_column["Size [bytes]", justify="right", style="green"]
        with Progress[transient=True] as progress:
            querying_task = progress.add_task["[red]RPM query...", start=False]
            current = 0
            for package in rpm_query:
                if current >= args.limit:
                    break
                rpm_table.add_row[f"{package['name']}-{package['version']}", f"{package['size']:,.0f}"]
                progress.console.print[f"[yellow]Processed package: [green]{package['name']}-{package['version']}"]
                current += 1
            progress.update[querying_task, advance=100.0]
            progress.console.print[rpm_table]

Thật đáng kinh ngạc khi thêm bảng và thanh tiến trình vào tập lệnh gốc dễ dàng như thế nào

Đây là giao diện của giao diện người dùng văn bản mới và được cải tiến

Hình ảnh

[Jose Vicente Nunez, CC BY-SA 4. 0]

2. tkinter

Tkinter là tập hợp các framework. TCL, TK và các vật dụng [Ttk]

Khung này đã trưởng thành và có rất nhiều tài liệu và ví dụ. Ngoài ra còn có tài liệu nghèo nàn, vì vậy tôi khuyên bạn nên làm theo hướng dẫn chính thức và sau đó, khi bạn nắm vững những điều cơ bản, hãy chuyển sang các hướng dẫn khác mà bạn quan tâm

Dưới đây là một số điều cần lưu ý

  • Kiểm tra xem hệ thống của bạn đã cài đặt đúng Tkinter chưa. ________số 8_______
  • Làm cho GUI của bạn phản ứng nhanh với các sự kiện bằng cách sử dụng các chức năng gọi lại [command=]
  • Tkinter giao tiếp bằng cách sử dụng các biến đặc biệt theo dõi các thay đổi cho bạn [Var, như
    $ ./rpmq_simple.py --limit 10
    linux-firmware-20210818: 395,099,476
    code-1.61.2: 303,882,220
    brave-browser-1.31.87: 293,857,731
    libreoffice-core-7.0.6.2: 287,370,064
    thunderbird-91.1.0: 271,239,962
    firefox-92.0: 266,349,777
    glibc-all-langpacks-2.32: 227,552,812
    mysql-workbench-community-8.0.23: 190,641,403
    java-11-openjdk-headless-11.0.13.0.8: 179,469,639
    iwl7260-firmware-25.30.13.0: 148,167,043
    0]

Mã trông như thế nào trong Tkinter?

#!/usr/bin/env python
"""
# rpmq_tkinter.py - A simple CLI to query the sizes of RPM on your system
This example is more complex because:
 * Uses callbacks [commands] to update the GUI and also deals
 * Deals with the placement of components using a frame with Grid and a flow layout
Author: Jose Vicente Nunez
"""
import argparse
import textwrap
from tkinter import *
from tkinter.ttk import *
from reporter import __is_valid_limit__
from reporter.rpm_query import QueryHelper


def __initial__search__[*, window: Tk, name: str, limit: int, sort: bool, table: Treeview] -> NONE:
    """
    Populate the table with an initial search using CLI args
    :param window:
    :param name:
    :param limit:
    :param sort:
    :param table:
    :return:
    """
    with QueryHelper[name=name, limit=limit, sorted_val=sort] as rpm_query:
        row_id = 0
        for package in rpm_query:
            if row_id >= limit:
                break
            package_name = f"{package['name']}-{package['version']}"
            package_size = f"{package['size']:,.0f}"
            table.insert[
                parent='',
                index='end',
                iid=row_id,
                text='',
                values=[package_name, package_size]
            ]
            window.update[]  # Update the UI as soon we get results
            row_id += 1


def __create_table__[main_w: Tk] -> Treeview:
    """
    * Create a table using a tree component, with scrolls on both sides [vertical, horizontal]
    * Let the UI 'pack' or arrange the components, not using a grid here
    * The table reacts to the actions and values of the components defined on the filtering components.
    :param main_w
    """
    scroll_y = Scrollbar[main_w]
    scroll_y.pack[side=RIGHT, fill=Y]
    scroll_x = Scrollbar[main_w, orient='horizontal']
    scroll_x.pack[side=BOTTOM, fill=X]
    tree = Treeview[main_w, yscrollcommand=scroll_y.set, xscrollcommand=scroll_x.set]
    tree.pack[]
    scroll_y.config[command=tree.yview]
    scroll_x.config[command=tree.xview]
    tree['columns'] = ['package_name', 'package_size']
    tree.column["#0", width=0, stretch=NO]
    tree.column["package_name", anchor=CENTER, width=500]
    tree.column["package_size", anchor=CENTER, width=100]
    tree.heading["#0", text="", anchor=CENTER]
    tree.heading["package_name", text="Name", anchor=CENTER]
    tree.heading["package_size", text="Size [bytes]", anchor=CENTER]
    return tree


def __cli_args__[] -> argparse.Namespace:
    """
    Command line argument parsing
    :return:
    """
    parser = argparse.ArgumentParser[description=textwrap.dedent[__doc__]]
    parser.add_argument[
        "--limit",
        type=__is_valid_limit__,  # Custom limit validator
        action="store",
        default=QueryHelper.MAX_NUMBER_OF_RESULTS,
        help="By default results are unlimited but you can cap the results"
    ]
    parser.add_argument[
        "--name",
        type=str,
        action="store",
        default="",
        help="You can filter by a package name."
    ]
    parser.add_argument[
        "--sort",
        action="store_false",
        help="Sorted results are enabled bu default, but you fan turn it off"
    ]
    return parser.parse_args[]


def __reset_command__[] -> None:
    """
    Callback to reset the UI form filters
    Doesn't trigger a new search. This is on purpose!
    :return:
    """
    query_v.set[args.name]
    limit_v.set[args.limit]
    sort_v.set[args.sort]


def __ui_search__[] -> None:
    """
    Re-do a search using UI filter settings
    :return:
    """
    for i in results_tbl.get_children[]:
        results_tbl.delete[i]
        win.update[]
    __initial__search__[
        window=win, name=query_v.get[], limit=limit_v.get[], sort=sort_v.get[], table=results_tbl]


def test[arg]:
    print[arg]


if __name__ == "__main__":
    args = __cli_args__[]
    win = Tk[]
    win.title["RPM Search results"]
    # Search frame with filtering options. Force placement using a grid
    search_f = LabelFrame[text='Search options:', labelanchor=N, relief=FLAT, padding=1]
    query_v = StringVar[value=args.name]
    query_e = Entry[search_f, textvariable=query_v, width=25]
    limit_v = IntVar[value=args.limit]
    limit_l = Label[search_f, text="Limit results: "]
    query_l = Spinbox[
        search_f,
        from_=1,  # from_ is not a typo and is annoying!
        to=QueryHelper.MAX_NUMBER_OF_RESULTS,
        textvariable=limit_v
    ]
    sort_v = BooleanVar[value=args.sort]
    sort_c = Checkbutton[search_f, text="Sort by size", variable=sort_v]
    search_btn = Button[search_f, text="Search RPM", command=__ui_search__]
    clear_btn = Button[search_f, text="Reset filters", command=__reset_command__]
    package_l = Label[search_f, text="Package name: "].grid[row=0, column=0, sticky=W]
    search_f.grid[column=0, row=0, columnspan=3, rowspan=4]
    limit_l.grid[row=1, column=0, sticky=W]
    query_e.grid[row=0, column=1, columnspan=2, sticky=W]
    query_l.grid[row=1, column=1, columnspan=1, sticky=W]
    sort_c.grid[row=2, column=0, columnspan=1, sticky=W]
    search_btn.grid[row=3, column=0, columnspan=2, sticky=W]
    clear_btn.grid[row=3, column=1, columnspan=1, sticky=W]
    search_f.pack[side=TOP, fill=BOTH, expand=1]
    results_tbl = __create_table__[win]
    results_tbl.pack[side=BOTTOM, fill=BOTH, expand=1]
    __initial__search__[
        window=win, name=query_v.get[], limit=limit_v.get[], sort=sort_v.get[], table=results_tbl]
    win.mainloop[]

Mã dài dòng hơn, chủ yếu là do xử lý sự kiện

Hình ảnh

[Jose Vicente Nunez, CC BY-SA 4. 0]

Tuy nhiên, điều đó cũng có nghĩa là bạn có thể chạy lại các truy vấn của mình sau khi tập lệnh bắt đầu bằng cách điều chỉnh các tham số trên khung tùy chọn tìm kiếm

3. Kính gửiPyGui

DearPyGui của Jonathan Hoffstadt là ứng dụng đa nền tảng [Linux, Windows, macOS] và có một số tính năng hay

Cài đặt DearPyGui

Nếu bạn có một hệ thống hiện tại [như Fedora 33 hoặc Windows 10 Pro], việc cài đặt sẽ đủ dễ dàng

$ pip install dearpygui

Đây là ứng dụng được viết lại trong DearPyGui

#!/usr/bin/env python
"""
# rpmq_dearpygui.py - A simple CLI to query the sizes of RPM on your system
Author: Jose Vicente Nunez
"""
import argparse
import textwrap

from reporter import __is_valid_limit__
from reporter.rpm_query import QueryHelper
import dearpygui.dearpygui as dpg

TABLE_TAG = "query_table"
MAIN_WINDOW_TAG = "main_window"


def __cli_args__[] -> argparse.Namespace:
    """
    Command line argument parsing
    :return:
    """
    parser = argparse.ArgumentParser[description=textwrap.dedent[__doc__]]
    parser.add_argument[
        "--limit",
        type=__is_valid_limit__,  # Custom limit validator
        action="store",
        default=QueryHelper.MAX_NUMBER_OF_RESULTS,
        help="By default results are unlimited but you can cap the results"
    ]
    parser.add_argument[
        "--name",
        type=str,
        action="store",
        default="",
        help="You can filter by a package name."
    ]
    parser.add_argument[
        "--sort",
        action="store_false",
        help="Sorted results are enabled bu default, but you fan turn it off"
    ]
    return parser.parse_args[]


def __reset_form__[]:
    dpg.set_value["package_name", args.name]
    dpg.set_value["limit_text", args.limit]
    dpg.set_value["sort_by_size", args.sort]


def __run_initial_query__[
        *,
        package: str,
        limit: int,
        sorted_elem: bool
] -> None:
    """
    Need to ensure the table gets removed.
    See issue: //github.com/hoffstadt/DearPyGui/issues/1350
    :return:
    """
    if dpg.does_alias_exist[TABLE_TAG]:
        dpg.delete_item[TABLE_TAG, children_only=False]
    if dpg.does_alias_exist[TABLE_TAG]:
        dpg.remove_alias[TABLE_TAG]
    with dpg.table[header_row=True, resizable=True, tag=TABLE_TAG, parent=MAIN_WINDOW_TAG]:
        dpg.add_table_column[label="Name", parent=TABLE_TAG]
        dpg.add_table_column[label="Size [bytes]", default_sort=True, parent=TABLE_TAG]
        with QueryHelper[
                name=package,
                limit=limit,
                sorted_val=sorted_elem
        ] as rpm_query:
            current = 0
            for package in rpm_query:
                if current >= args.limit:
                    break
                with dpg.table_row[parent=TABLE_TAG]:
                    dpg.add_text[f"{package['name']}-{package['version']}"]
                    dpg.add_text[f"{package['size']:,.0f}"]
                current += 1


def __run__query__[] -> None:
    __run_initial_query__[
        package=dpg.get_value["package_name"],
        limit=dpg.get_value["limit_text"],
        sorted_elem=dpg.get_value["sort_by_size"]
    ]


if __name__ == "__main__":

    args = __cli_args__[]

    dpg.create_context[]
    with dpg.window[label="RPM Search results", tag=MAIN_WINDOW_TAG]:
        dpg.add_text["Run a new search"]
        dpg.add_input_text[label="Package name", tag="package_name", default_value=args.name]
        with dpg.tooltip["package_name"]:
            dpg.add_text["Leave empty to search all packages"]
        dpg.add_checkbox[label="Sort by size", tag="sort_by_size", default_value=args.sort]
        dpg.add_slider_int[
            label="Limit",
            default_value=args.limit,
            tag="limit_text",
            max_value=QueryHelper.MAX_NUMBER_OF_RESULTS
        ]
        with dpg.tooltip["limit_text"]:
            dpg.add_text[f"Limit to {QueryHelper.MAX_NUMBER_OF_RESULTS} number of results"]
        with dpg.group[horizontal=True]:
            dpg.add_button[label="Search", tag="search", callback=__run__query__]
            with dpg.tooltip["search"]:
                dpg.add_text["Click here to search RPM"]
            dpg.add_button[label="Reset", tag="reset", callback=__reset_form__]
            with dpg.tooltip["reset"]:
                dpg.add_text["Reset search filters"]
        __run_initial_query__[
            package=args.name,
            limit=args.limit,
            sorted_elem=args.sort
        ]

    dpg.create_viewport[title='RPM Quick query tool']
    dpg.setup_dearpygui[]
    dpg.show_viewport[]
    dpg.start_dearpygui[]
    dpg.destroy_context[]

Lưu ý rằng DearPyGui sử dụng ngữ cảnh khi lồng các thành phần, giúp tạo GUI dễ dàng hơn nhiều. Mã này cũng ít dài dòng hơn mã Tkinter và hỗ trợ cho các loại tốt hơn nhiều [ví dụ: PyCharm cung cấp các đối số tự động hoàn thành cho các phương thức, v.v. ]

[ Tìm hiểu cách hiện đại hóa CNTT hoạt động trên nhiều cấp độ để loại bỏ nợ kỹ thuật cả về thời gian và tiền bạc. Tải xuống Giảm nợ kỹ thuật. ]

DearPyGui vẫn còn rất trẻ [phiên bản 1. 0. 3 tại thời điểm viết bài này] và có một vài lỗi, đặc biệt là trên các bản phân phối Linux cũ hơn, nhưng nó có vẻ rất hứa hẹn và đang trong giai đoạn phát triển tích cực

Vậy giao diện người dùng trông như thế nào trong DearPyGui?

Hình ảnh

[Jose Vicente Nunez, CC BY-SA 4. 0]

Các mẹo khác để cải thiện ứng dụng người dùng của bạn

  • Bộ chứa Linux

    • Giới thiệu thực tế về thuật ngữ container
    • Sơn lót container
    • Tải ngay. Bản dùng thử Red Hat OpenShift
    • sách điện tử. Podman trong hành động
    • Hội thảo trực tuyến. Đồng bộ hóa và quản lý các ứng dụng dựa trên bộ chứa trên nhiều c…

    Bạn có nhiều tùy chọn trong Python để làm cho tập lệnh của mình thân thiện hơn với người dùng. Ngay cả những hành động đơn giản như sử dụng Argparse cũng sẽ có tác động lớn đến cách sử dụng tập lệnh
  • Tìm tài liệu chính thức và nhóm người dùng. Ngoài ra, đừng quên có những hướng dẫn tốt ngoài kia
  • Rich và Tkinter là những lựa chọn thay thế hoàn thiện để giúp giao diện người dùng của bạn tốt hơn nhiều và DearPyGUI có vẻ rất hứa hẹn
  • Không phải mọi thứ đều cần một giao diện người dùng phức tạp. Nhưng các khung như Rich làm cho việc cải thiện chương trình của bạn trở nên đơn giản bằng cách làm cho các ngoại lệ và kiểm tra đối tượng dễ đọc hơn trên các tập lệnh chỉ có văn bản của bạn

Xem các bài viết liên quan này trên Enable Sysadmin

Hình ảnh

Viết và kiểm tra đơn vị một ứng dụng Python để truy vấn cơ sở dữ liệu RPM

Viết chương trình Python in danh sách phần mềm được cài đặt trên hệ thống của bạn, sau đó kiểm tra xem ứng dụng có hoạt động chính xác không

Đã đăng. Ngày 1 tháng 12 năm 2021

Tác giả. Jose Vicente Nunez [Sudoer]

Hình ảnh

Đóng gói các ứng dụng để cài đặt trên các máy khác bằng Python

Sử dụng môi trường ảo, pip và công cụ thiết lập để đóng gói các ứng dụng cùng với các phần phụ thuộc của chúng để cài đặt trơn tru trên các máy tính khác

Đã đăng. Ngày 2 tháng 12 năm 2021

Tác giả. Jose Vicente Nunez [Sudoer]

Hình ảnh

Hướng dẫn của quản trị viên hệ thống để chứa các ứng dụng

Tò mò về cách chứa các ứng dụng Linux của bạn?

Đã đăng. Ngày 3 tháng 11 năm 2020

Tác giả. Scott McCarty [Cựu sinh viên Sudoer, Mũ đỏ]

chủ đề. Python   Phần mềm   Lập trình

Jose Vicente Nunez

Người cha và người chồng tự hào, nhà phát triển phần mềm và quản trị viên hệ thống. Á hậu giải trí và đam mê. Thêm về tôi

Hội nghị thượng đỉnh mũ đỏ 2022. theo yêu cầu

Nhận thông tin mới nhất về Ansible, Red Hat Enterprise Linux, OpenShift, v.v. từ sự kiện ảo theo yêu cầu của chúng tôi

Đăng kí miễn phí

Nội dung liên quan

Hình ảnh

Tìm hiểu cách Unix ảnh hưởng đến Linux, hiểu các danh sách và từ điển Ansible và các mẹo khác dành cho quản trị viên hệ thống

TUI trong Python là gì?

[python Terminal Toolkit] là thư viện giao diện người dùng dựa trên văn bản [TUI] Được phát triển từ dự án pyCuT đã ngừng hoạt động và lấy cảm hứng từ sự kết hợp .

Làm cách nào để tạo GUI trong Python?

Tkinter là thư viện GUI chuẩn cho Python. .
Nhập mô-đun Tkinter
Tạo cửa sổ chính của ứng dụng GUI
Thêm một hoặc nhiều tiện ích nêu trên vào ứng dụng GUI
Nhập vòng lặp sự kiện chính để thực hiện hành động đối với từng sự kiện do người dùng kích hoạt

Python có tốt cho giao diện người dùng không?

Mặc dù cực kỳ hữu ích cho các lĩnh vực khoa học dữ liệu và máy học, Python cũng rất tuyệt vời để phát triển giao diện người dùng đồ họa . Trên thực tế, nó có nhiều khung mà ngay cả những người mới bắt đầu cũng có thể sử dụng để dễ dàng bắt đầu phát triển GUI.

Chủ Đề