Форум программистов, компьютерный форум, киберфорум
iamvic
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
Путевые заметки в процессе познания Python и PyQt/PySide.
Помни - только тег CODE не портит код добавлением пробела в начало пустой строки.

К вопросу о том, какой дизайнер нужен...

Запись от iamvic размещена 22.11.2023 в 14:16
Показов 1554 Комментарии 3

Если задаться вопросом "Кто способен реализовать программный проект сам, один и без ансамбля?", то можно дать однозначный ответ "это программист" .

У программиста может быть масса недостатков, например, отсутствие художественного вкуса, однобокое знание иностранных языков, невнятная речь, профессиональное занудство и прочее, что не мешает ему быть специалистом в своей области. Он способен понять проблему, предложить решение, детально проработать постановку (что, где, когда, кто, как и почему) и реализовать задачу выбранными средствами. Вопрос только в мотивации (время, деньги, интерес ).

Зная о своих недостатках, этот программист ещё на начальной стадии разработки заложится на то, что выполнение некоторых частей задачи лучше было бы делегировать специалистам соответствующего профиля. Например, переводы на различные языки народов мира лучше сделает переводчик, а придать неимоверно привлекательный вид элементам графического интерфейса - стилист. Надо только дать им такую возможность, а творить они смогут независимо от программиста.

Например, можно воспользоваться "методом большой кучи", исходя из принципа "грузи навалом - сервис узнает своих", как это сделано в нижеприведённом примере, основанном на коде из предыдущей заметки К вопросу о неявном назначении родительской опеки...

clipboard_probe.py:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Clipboard Probe v0.005
import glob, os, sys
from PyQt5 import QtCore, QtGui, QtWidgets
 
APP_NAME = 'Clipboard Probe v0.005'
 
def get_screen_geo_by_pos(point_pos = QtCore.QPoint(0, 0)):
    screens = QtWidgets.QApplication.instance().screens()
    selected_screen = screens[
        QtWidgets.QApplication.desktop().primaryScreen()]
    if len(screens) > 1:
        for i in range(len(screens)):
            if screens[i].geometry().contains(point_pos):
                selected_screen = screens[i]
                break
    return selected_screen.availableGeometry()
 
def set_quarter_screen(client, screen_geo):
    client.move(screen_geo.x() + screen_geo.width() // 4,
                screen_geo.y() + screen_geo.height() // 4)
    client.resize(screen_geo.width() // 2,
                  screen_geo.height() // 2)
 
def tr_app(context, text):
    return QtWidgets.QApplication.instance().translate(context, text)
 
class Main_window(QtWidgets.QMainWindow):
    def __init__(self, parent = None,
                 point_pos = QtCore.QPoint(0, 0)):
 
        super(Main_window, self).__init__(parent)
 
        central_widget = QtWidgets.QWidget()
        status_bar = QtWidgets.QStatusBar(self)
        text_editor = QtWidgets.QPlainTextEdit()
        main_map = QtWidgets.QVBoxLayout()
        clip_board = QtWidgets.QApplication.instance().clipboard()
 
        main_map.addWidget(text_editor)
        central_widget.setLayout(main_map)
        self.setCentralWidget(central_widget)
        self.setStatusBar(status_bar)
 
        self.setWindowTitle(tr_app('mainwindow', 'Сlipboard observer'))
        self.setObjectName('mainwindow')
        text_editor.setLineWrapMode(QtWidgets.QPlainTextEdit.WidgetWidth)
        text_editor.setPlainText(clip_board.text())
        text_editor.setObjectName('texteditor')
        status_bar.setObjectName('statusbar')
 
        QtCore.QMetaObject.connectSlotsByName(self)
        clip_board.dataChanged.connect(self.on_clipboard_dataChanged)
 
        set_quarter_screen(self, get_screen_geo_by_pos(point_pos))
 
    def on_clipboard_dataChanged(self):
        text_editor = self.findChild(QtWidgets.QPlainTextEdit,
                                     'texteditor')
        status_bar = self.findChild(QtWidgets.QStatusBar, 'statusbar')
        text_editor.setPlainText(self.sender().text())
        status_bar.clearMessage()
 
    def on_texteditor_textChanged(self):
        clip_board = QtWidgets.QApplication.instance().clipboard()
        status_bar = self.findChild(QtWidgets.QStatusBar, 'statusbar')
        if self.sender().toPlainText() != clip_board.text():
            status_bar.showMessage(
                tr_app('mainwindow',
                       'Text changed! Press Ctrl-A, Ctrl-Ins to put'
                       ' to clipboard or Ctrl-Z to drop.')
                )
        else:
            status_bar.clearMessage()
 
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    pack_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    qtbase_dir = QtCore.QLibraryInfo.location(
        QtCore.QLibraryInfo.TranslationsPath)
 
    style_set = ''
    l_qss = [str(n) for n in glob.glob(os.path.join(pack_dir, '*.qss'))]
    for n in l_qss:
        with open(n, 'r') as f_qss:
            style_set += '{!s}\n'.format(f_qss.read())
    app.setStyleSheet(style_set)
 
    c_lang = QtCore.QLocale().name()[0:2]
#    c_lang = 'en'
    l_tr = [QtCore.QTranslator()]
    n_tr = 'qtbase_{!s}.qm'.format(c_lang)
    if l_tr[-1].load(n_tr, qtbase_dir):
        app.installTranslator(l_tr[-1])
    else:
        t = l_tr[-1]
        l_tr.remove(t)
        t.deleteLater()
 
    l_qm = [str(n) for n in glob.glob(
            os.path.join(pack_dir, '*_{!s}.qm'.format(c_lang)))]
    for n in l_qm:
        l_tr.append(QtCore.QTranslator())
        if l_tr[-1].load(n, pack_dir):
            app.installTranslator(l_tr[-1])
        else:
            t = l_tr[-1]
            l_tr.remove(t)
            t.deleteLater()
 
    mwin = Main_window(point_pos = QtGui.QCursor.pos())
    mwin.show()
    sys.exit(app.exec_())

Теперь стилист может выложить в каталог, содержащий файлы кода (типа *.py), свои файлы типа *.qss с оригинальными стилевыми решениями. Все они будут загружены при старте приложения и применены к соответствующим элементам оконного интерфейса.

main.qss:
XML
1
2
3
QMainWindow#mainwindow {background-color: olivedrab;}
QStatusBar#statusbar {background: white; color: maroon;}
QPlainTextEdit#texteditor {background-color: palegoldenrod; font: bold; font-family: monospace;}

Переводчик тоже может выкладывать туда свои переводы (файлы типа *.qm) по мере их готовности. При старте приложения будут загружены только те переводы, которые соответствуют текущим настройкам системной локали.

Что характерно, это совершенствование стиля и расширение базы языкового покрытия будет происходить без участия программиста. Он уже сделал всё, что мог - код написан, инструкции выданы.

И даже, если программисту потребуется как-то перетасовать элементы графического интерфейса с целью достижения большего удобства пользования, то это никак не затронет всё то, что уже сделано, делается или будет делаться стилистом и переводчиком.

Однако, если вы вдруг подумали, что дизайнер вообще руки не прикладывал к разработке этой программы, то вы глубоко ошибаетесь. Потому что программист - он и есть этот самый дизайнер. Ведь дизайн - это не про красивости, как некоторые ошибочно полагают. Не царское это дело - заборы красить . Дизайн - это про эргономику, фактически - про разработку и отладку сценариев взаимодействия пользователя с программой. Дополнительно отягощает ситуацию то, что разработчик никогда не знает точно в каких условиях будет эксплуатироваться программа. Сегодня пользователь сидит в кабинете, увешанном HDMI-мониторами, а завтра - на выезде с одним чахлым ноутбуком и ему срочно надо... А всё это уже продумал и реализовал программист. И дизайн у него не монолитно-железобетонный , а подвижный, адаптирующийся под возможности техники. Вот такой дизайнер - нужен!

Потому что, если потребуется, он и с Qt Designer-ом не оплошает - сможет построить графический интерфейс с его помощью не хуже, чем в оригинале.

clipboard_probe.py:
Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Clipboard Probe v0.006
import glob, os, sys
from PyQt5 import uic, QtCore, QtGui, QtWidgets
 
APP_NAME = 'Clipboard Probe v0.006'
 
def get_screen_geo_by_pos(point_pos = QtCore.QPoint(0, 0)):
    screens = QtWidgets.QApplication.instance().screens()
    selected_screen = screens[
        QtWidgets.QApplication.desktop().primaryScreen()]
    if len(screens) > 1:
        for i in range(len(screens)):
            if screens[i].geometry().contains(point_pos):
                selected_screen = screens[i]
                break
    return selected_screen.availableGeometry()
 
def set_quarter_screen(client, screen_geo):
    client.move(screen_geo.x() + screen_geo.width() // 4,
                screen_geo.y() + screen_geo.height() // 4)
    client.resize(screen_geo.width() // 2,
                  screen_geo.height() // 2)
 
def tr_app(context, text):
    return QtWidgets.QApplication.instance().translate(context, text)
 
class Main_window(QtWidgets.QMainWindow):
    def __init__(self, parent = None,
                 point_pos = QtCore.QPoint(0, 0)):
 
        super(Main_window, self).__init__(parent)
        uic.loadUi(
            os.path.join(
                os.path.dirname(os.path.abspath(sys.argv[0])),
                'mwin.ui'),
            self)
 
        clip_board = QtWidgets.QApplication.instance().clipboard()
        text_editor = self.findChild(QtWidgets.QPlainTextEdit,
                                     'texteditor')
        text_editor.setPlainText(clip_board.text())
        clip_board.dataChanged.connect(self.on_clipboard_dataChanged)
        set_quarter_screen(self, get_screen_geo_by_pos(point_pos))
 
    def on_clipboard_dataChanged(self):
        text_editor = self.findChild(QtWidgets.QPlainTextEdit,
                                     'texteditor')
        status_bar = self.findChild(QtWidgets.QStatusBar, 'statusbar')
        text_editor.setPlainText(self.sender().text())
        status_bar.clearMessage()
 
    def on_texteditor_textChanged(self):
        clip_board = QtWidgets.QApplication.instance().clipboard()
        status_bar = self.findChild(QtWidgets.QStatusBar, 'statusbar')
        if self.sender().toPlainText() != clip_board.text():
            status_bar.showMessage(
                tr_app('main',
                       'Text changed! Press Ctrl-A, Ctrl-Ins to put'
                       ' to clipboard or Ctrl-Z to drop.')
                )
        else:
            status_bar.clearMessage()
 
if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    pack_dir = os.path.dirname(os.path.abspath(sys.argv[0]))
    qtbase_dir = QtCore.QLibraryInfo.location(
        QtCore.QLibraryInfo.TranslationsPath)
 
    style_set = ''
    l_qss = [str(n) for n in glob.glob(os.path.join(pack_dir, '*.qss'))]
    for n in l_qss:
        with open(n, 'r') as f_qss:
            style_set += '{!s}\n'.format(f_qss.read())
    app.setStyleSheet(style_set)
 
    c_lang = QtCore.QLocale().name()[0:2]
#    c_lang = 'en'
    l_tr = [QtCore.QTranslator()]
    n_tr = 'qtbase_{!s}.qm'.format(c_lang)
    if l_tr[-1].load(n_tr, qtbase_dir):
        app.installTranslator(l_tr[-1])
    else:
        t = l_tr[-1]
        l_tr.remove(t)
        t.deleteLater()
 
    l_qm = [str(n) for n in glob.glob(
            os.path.join(pack_dir, '*_{!s}.qm'.format(c_lang)))]
    for n in l_qm:
        l_tr.append(QtCore.QTranslator())
        if l_tr[-1].load(n, pack_dir):
            app.installTranslator(l_tr[-1])
        else:
            t = l_tr[-1]
            l_tr.remove(t)
            t.deleteLater()
 
    mwin = Main_window(point_pos = QtGui.QCursor.pos())
    mwin.show()
    sys.exit(app.exec_())

mwin.ui:
XML
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
 <class>mainwindow</class>
 <widget class="QMainWindow" name="mainwindow">
  <property name="geometry">
   <rect>
    <x>0</x>
    <y>0</y>
    <width>268</width>
    <height>261</height>
   </rect>
  </property>
  <property name="windowTitle">
   <string>Clipboard observer</string>
  </property>
  <widget class="QWidget" name="centralwidget">
   <layout class="QVBoxLayout" name="verticalLayout">
    <item>
     <widget class="QPlainTextEdit" name="texteditor"/>
    </item>
   </layout>
  </widget>
  <widget class="QMenuBar" name="menubar">
   <property name="geometry">
    <rect>
     <x>0</x>
     <y>0</y>
     <width>268</width>
     <height>32</height>
    </rect>
   </property>
  </widget>
  <widget class="QStatusBar" name="statusbar"/>
 </widget>
 <resources/>
 <connections/>
</ui>

Хоть и не без греха... Например, стилист даже не заметит этой революции, а вот переводчика коснётся. Переделывать существующие переводы нужды особой нет, но к ним придётся дописывать новые, поскольку часть данных, требующих перевода, перейдёт из скриптов (*.py) в файлы дизайна (*.ui). Наверняка есть ещё какие-то сюрпризы...

Стоит ли овчинка выделки - каждый решает сам. Не был бы прибыток горше убытка... Но дизайнер должен оставаться программистом
Размещено в Памятка
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 3
Комментарии
  1. Старый комментарий
    Аватар для AlexProgramm
    Эх, знал бы Python, ходил бы тогда, тоже героем!(с)
    Запись от AlexProgramm размещена 22.11.2023 в 21:55 AlexProgramm вне форума
  2. Старый комментарий
    AlexProgramm, честно говоря, не понял, чем Вам помочь. Посмотрел Ваш блог - всё отлично! Владение Джавой - серьёзный аргумент, которым можно потрясти заказчика. Изучили - отлично! А поскольку знания без практики мертвы, то пора переходить к практическому применению. Там же настолько широкая поляна, что любой прикладухе найдётся место. Остаётся только включить фантазию...
    Запись от iamvic размещена 23.11.2023 в 10:47 iamvic вне форума
  3. Старый комментарий
    Аватар для AlexProgramm
    Цитата Сообщение от iamvic
    AlexProgramm, честно говоря, не понял, чем Вам помочь. Посмотрел Ваш блог - всё отлично! Владение Джавой - серьёзный аргумент, которым можно потрясти заказчика. Изучили - отлично! А поскольку знания без практики мертвы, то пора переходить к практическому применению. Там же настолько широкая поляна, что любой прикладухе найдётся место. Остаётся только включить фантазию...
    Спасибо! Зашли - значит помогли
    Запись от AlexProgramm размещена 23.11.2023 в 10:55 AlexProgramm вне форума
 
Новые блоги и статьи
Запустил конкурс "тем и промптов для текстовых квестов созданных почти чисто ИИ"
Adler 06.10.2026
Всем привет! За последние три-четыре дня я создал более 16 текстовых квестовых игр используя преимущественно по одному запросу к ИИ на игру. Мне так понравилось смотреть все ветки/ сцены во всех. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru