Использование нескольких JFrames: хорошая или плохая практика? [закрыто]

531

Я разрабатываю приложение, которое отображает изображения и воспроизводит звуки из базы данных. Я пытаюсь решить, следует ли использовать отдельный JFrame для добавления изображений в базу данных из графического интерфейса.

Мне просто интересно, является ли хорошей практикой использование нескольких окон JFrame?

разносчик
источник
11
Только если вы нацелены на настройку нескольких мониторов!
ДНК
17
Я также утверждаю, что это не зависит от языка и связано с пользовательским интерфейсом больше, чем с Java.
wchargin
6
Я бы согласился с этим @WChargin. Этот вопрос стал более ценным, чем я мог предположить!
Разносчик
1
Я заметил, что начинающие (такие как я) обычно используют несколько JFrames. Вероятно потому, что его проще вызвать изнутри основного JFrame, чем с помощью, скажем, CardLayout. Хотя в некоторых случаях его не рекомендуется использовать.
Hoodlum
Отладка была бы похожа на еду кактуса .. это не рекомендуется.
Таслим Осени

Ответы:

447

Мне просто интересно, является ли хорошей практикой использование нескольких JFrames?

Плохая (плохая, плохая) практика.

  • Недружественный пользователь: пользователь видит несколько значков на панели задач, ожидая увидеть только один. Плюс побочные эффекты от проблем с кодированием.
  • Кошмар, чтобы кодировать и поддерживать:
    • Модальный диалог предлагает легкую возможность сосредоточить внимание на содержание этого диалога - выбрать / исправить / отменить это, затем продолжить. Несколько кадров нет.
    • Диалог (или плавающая панель инструментов) с родительским элементом появится при нажатии на родительского элемента - вам придется реализовать это в кадрах, если это было желаемое поведение.

Существует множество способов отображения множества элементов в одном графическом интерфейсе, например:

  • CardLayout(короткая демонстрация. ) Хорош для:
    1. Отображение диалогов как в мастере.
    2. Отображение списка, дерева и т. Д. Для элементов, имеющих связанный компонент.
    3. Переключение между отсутствующим компонентом и видимым компонентом.
  • JInternalFrame/JDesktopPane обычно используется для MDI .
  • JTabbedPane для групп компонентов.
  • JSplitPane Способ отображения двух компонентов, важность которых для одного или другого (размер) зависит от того, что делает пользователь.
  • JLayeredPane далеко много хорошо .. слоистых компонентов.
  • JToolBarобычно содержит группы действий или элементов управления. Может перетаскиваться по всему графическому интерфейсу или полностью отключаться в соответствии с потребностями пользователя. Как упоминалось выше, будет минимизировано / восстановлено в соответствии с действиями родителя.
  • Как элементы в JList(простой пример ниже).
  • Как узлы в JTree.
  • Вложенные макеты .

Но если эти стратегии не работают для конкретного варианта использования, попробуйте следующее. Создайте один главный JFrame, затем появите JDialogили JOptionPaneсоздайте экземпляры для остальных свободно плавающих элементов, используя рамку в качестве родительского для диалогов.

Много изображений

В этом случае, когда несколько элементов являются изображениями, было бы лучше использовать одно из следующих:

  1. Один JLabel(по центру на панели прокрутки) для отображения любого изображения, интересующего пользователя в данный момент. Как видно в ImageViewer.
  2. Одна строка JList. Как видно из этого ответа . «Однорядная» часть этого работает, только если они имеют одинаковые размеры. Альтернативно, если вы готовы масштабировать изображения на лету, и все они имеют одинаковое соотношение сторон (например, 4: 3 или 16: 9).

Эндрю Томпсон
источник
4
@ AndrewThompson Я никогда раньше не сталкивался с ситуацией, когда мне требовалось несколько JFrameсекунд, и никогда не рассматривал эти проблемы, спасибо за разъяснения!
Джеффри
4
@ user417896 "Просто зависит." Нет, это не так. Я использовал Gimp. Это ужасно и должно быть MDI.
Эндрю Томпсон
4
@ryvantage "Должен ли (Excel) быть MDI?" Хороший вопрос. Я чувствую, что это должно быть предложено пользователю обоими способами (конечно, не только в форме MDI). Например: 1) В настоящее время я использую TextPad, и по своему выбору конфигурация открывает отдельные экземпляры, каждый из которых предлагает несколько документов, показанных в списке. 2) Хотя я обычно использую FF в режиме вкладок, иногда я перетаскиваю вкладку в новое окно. - Общим фактором в примерах является выбор пользователя. Доставь приложение. «Однако пользователь хочет это».
Эндрю Томпсон
12
@AndrewThompson Вы только что опровергли свой собственный аргумент своим последним комментарием. В своем основном ответе вы говорите, что это плохая практика, и ее никогда не следует делать, но в своем комментарии выше вы говорите, что иногда вам нравится SDI, и мы должны предложить нашим пользователям выбор. Конечно, это именно то, что пользователь417896 говорил выше. Это зависит. Это одна из самых больших ненавистей моего питомца к моим коллегам-разработчикам. Тот факт, что многие из них становятся религиозно фанатичными в отношении так называемых «лучших практик». У нас не было бы инновационных интерфейсов, которые есть у нас сегодня, если бы мы все придерживались «лучших практик» и не думали за пределами площади.
DuncanKinnear
4
Огромное обобщение! Нет ничего плохого в том, чтобы позволить пользователю управлять своими окнами индивидуально и получать к ним доступ индивидуально с панели задач. Хорошая практика - знать все варианты и выбирать один разумно. Конечно, есть случаи, когда несколько JFrames имеют большой смысл.
Дауд ибн Карим
203

Многофункциональный JFrameподход был тем, что я реализовал с тех пор, как начал программировать приложения Swing. По большей части, я сделал это в начале, потому что я не знал ничего лучше. Тем не менее , по мере того, как я становился зрелым в своем опыте и знаниях в качестве разработчика и начал читать и воспринимать мнения многих более опытных разработчиков Java в Интернете, я попытался отойти от многократного JFrameподхода (как в текущих проектах, так и в будущих проектах). ) только встретиться с ... получить это ... сопротивление от моих клиентов! Когда я начал внедрять модальные диалоги для управления «дочерними» окнами и окнами JInternalFrameдля отдельных компонентов, мои клиенты начали жаловаться!Я был очень удивлен, поскольку делал то, что считал лучшей практикой! Но, как говорится, «счастливая жена - это счастливая жизнь». То же самое касается ваших клиентов. Конечно, я являюсь подрядчиком, поэтому мои конечные пользователи имеют прямой доступ ко мне, разработчику, что, очевидно, не является обычным сценарием.

Итак, я собираюсь объяснить преимущества множественного JFrameподхода, а также рассказать о некоторых минусах, представленных другими.

  1. Предельная гибкость в расположении - позволяя отдельным JFrameэлементам, вы даете конечному пользователю возможность распределять и контролировать то, что находится на его экране. Концепция чувствует себя «открытой» и не стесняющей. Вы теряете это, когда идете к одному большому JFrameи кучке JInternalFrameс.
  2. Хорошо работает для очень модульных приложений. В моем случае большинство моих приложений имеют 3-5 больших модулей, которые действительно не имеют никакого отношения друг к другу. Например, один модуль может быть панелью мониторинга продаж, а другой - панелью учета. Они не разговаривают друг с другом или что-то еще. Однако руководитель может захотеть открыть и то, и другое, поскольку отдельные панели на панели задач облегчают его жизнь.
  3. Позволяет конечным пользователям легко ссылаться на внешние материалы. Однажды у меня возникла такая ситуация: у моего приложения был «просмотрщик данных», из которого можно нажать «Добавить новый», и он откроет экран ввода данных. Изначально оба были JFrameс. Однако я хотел, чтобы экран ввода данных был тем, JDialogчьим родителем был просмотрщик данных. Я внес изменение, и сразу же мне позвонил конечный пользователь, который сильно полагался на то, что он может свернуть или закрыть средство просмотра и оставить редактор открытым, пока он ссылается на другую часть программы (или веб-сайт, который я не помню). Он не на мульти-мониторе, поэтому ему нужно, чтобы диалог ввода был первым и что-то ещебыть вторым, с просмотром данных полностью скрытым. Это было невозможно с a JDialogи, конечно, было бы невозможно и с a JInternalFrame. Я неохотно изменил это, чтобы быть отдельным JFramesдля его здравомыслия, но это преподало мне важный урок.
  4. Миф: трудно кодировать - это не так в моем опыте. Я не понимаю, почему было бы легче создать, JInternalFrameчем JFrame. На самом деле, по моему опыту, JInternalFramesпредлагаем гораздо меньше гибкости. Я разработал систематический способ обработки открывания и закрывания JFrames в моих приложениях, который действительно хорошо работает. Я почти полностью контролирую фрейм из самого кода фрейма; создание нового фрейма, SwingWorkerкоторый управляет извлечением данных в фоновых потоках и кода графического интерфейса пользователя в EDT, восстановление / вывод на передний план фрейма, если пользователь пытается открыть его дважды, и т. д. Все, что вам нужно, это открыть мой JFrameфайл. вызовите открытый статический метод open()и метод open в сочетании сwindowClosing() событие обрабатывает все остальное (фрейм уже открыт? он не открыт, но загружается? и т. д.). Я сделал этот подход шаблоном, чтобы его не сложно было реализовать для каждого фрейма.
  5. Миф / Недоказанный: Ресурс Тяжелый - я хотел бы увидеть некоторые факты за этим умозрительным утверждением. Хотя, возможно, вы могли бы сказать, что JFrameтребуется больше места, чем JInternalFrame, даже если вы откроете 100 JFrameс, сколько ресурсов вы бы действительно потребляли? Если вас беспокоит утечка памяти из-за ресурсов: вызов dispose()освобождает все ресурсы, используемые фреймом для сборки мусора (и, опять же, я говорю, a JInternalFrameдолжен вызывать точно такую ​​же проблему).

Я много писал и чувствую, что могу писать больше. В любом случае, я надеюсь, что за меня не проголосуют просто потому, что это непопулярное мнение. Вопрос явно ценный, и я надеюсь, что дал ценный ответ, даже если это не общее мнение.

Отличным примером нескольких кадров / одного документа на кадр ( SDI ) по сравнению с одним кадром / несколькими документами на кадр ( MDI ) является Microsoft Excel. Некоторые из преимуществ MDI:

  • можно иметь несколько окон непрямоугольной формы, чтобы они не скрывали рабочий стол или другое окно от другого процесса (например, веб-браузера)
  • во время записи во втором окне Excel можно открыть окно из другого процесса через одно окно Excel - при использовании MDI попытка записи в одном из внутренних окон даст фокус всему окну Excel, следовательно, скрывая окно от другого процесса
  • на разных экранах можно размещать разные документы, что особенно полезно, если экраны не имеют одинакового разрешения

SDI (интерфейс с одним документом, т. Е. Каждое окно может иметь только один документ):

введите описание изображения здесь

MDI (многодокументный интерфейс, т. Е. Каждое окно может иметь несколько документов):

введите описание изображения здесь

ryvantage
источник
16
Хорошо продуманный. Если у вас есть несколько модулей, которые не имеют ничего общего друг с другом, почему бы не создать отдельные приложения? Кроме того, нет ограничений в том, что вы должны использовать модальные диалоги, вы можете использовать немодальные диалоги, чтобы служить вторым «фреймом».
Джеффри
Очень хороший ответ и подробный ответ, хотя я должен согласиться с @kleopatra по этому вопросу. Однажды у меня было приложение с более чем сотней экранов, где пользователи хотели сравнивать выходные данные с нескольких экранов / одного экрана с разными входами. Мы создали собственную систему управления окнами, чтобы мы могли это сделать. Пользователям было просто удобнее иметь 2 JFrames, чтобы они были рядом друг с другом;)
javatarz
Хотя я понимаю ваш аргумент, я все же предпочел бы иметь все в одном JFrameи большой родитель JTabbedPane; но с возможностью открыть второе окно (или даже больше), где макет может отличаться, предлагая, следовательно, гибридное поведение, когда любители SDI довольны и MDI тоже. Во всех случаях я всегда считал JInternalFrameужасным паттерном, который доставляет вам все неудобства обоих миров. Гибкость, которую они предлагают, просто отстой, и они поглощают много драгоценного экранного пространства ни для каких реальных целей.
Гийом Поле,
Я согласен, что SDI иногда подходит (и пользователи часто предпочитают его). Есть еще один недостаток, и я, к сожалению, пока не нашел обходного пути для этого: каждый из них JFrameимеет свой значок на панели задач. Иногда это именно то, что вы хотите, но иногда это не так. В WinAPI это легко настроить, но в Swing кажется, что это невозможно.
Сума
@ Сума в этом случае, я думаю, я бы выбрал более JDialogчем JFrame.
ryvantage
51

Я бы хотел противопоставить аргумент "не дружественный пользователю" примером, с которым я только что работал.

В нашем приложении у нас есть главное окно, в котором пользователи запускают различные «программы» в виде отдельных вкладок. В максимально возможной степени мы старались держать наше приложение в этом единственном окне.

Одна из «программ», которые они запускают, представляет список отчетов, которые были сгенерированы системой, и пользователь может щелкнуть значок в каждой строке, чтобы открыть диалоговое окно просмотра отчетов. Этот вьюер показывает эквивалент страниц (4) в книжной / альбомной ориентации отчета, поэтому пользователям нравится, что это окно довольно большое, почти полностью заполняющее их экраны.

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

Некоторое время я отказывался от этого запроса, так как не думал, что это хорошее решение. Однако мое мнение изменилось, когда я узнал, как пользователи обходят этот «недостаток» нашей системы.

Они открывали программу просмотра, используя функцию «Сохранить как», чтобы сохранить отчет в виде PDF-файла в определенный каталог, используя Acrobat Reader, чтобы открыть файл PDF, и затем они делали то же самое со следующим отчетом. У них будет несколько читателей Acrobat, работающих с различными выводами отчетов, которые они хотят просмотреть.

Поэтому я смягчился и сделал зрителя немодальным. Это означает, что у каждого зрителя есть значок на панели задач.

Когда последняя версия была выпущена для них на прошлой неделе, подавляющим ответом было то, что они ЛЮБЯТ это. Это было одним из наших самых популярных последних улучшений в системе.

Итак, вы идете вперед и говорите своим пользователям, что то, что они хотят, плохо, но в конечном итоге это не принесет вам пользы.

НЕКОТОРЫЕ ЗАМЕЧАНИЯ:

  • Кажется, лучше всего использовать JDialog для этих немодальных окон.
  • Используйте конструкторы, которые используют новый, ModalityTypeа не логический modalаргумент. Это то, что дает этим диалогам значок панели задач.
  • Для немодальных диалогов, передайте в конструктор нулевого родителя, но найдите его относительно своего «родительского» окна.
  • В версии 6 Java на Windows есть ошибка, которая означает, что ваше главное окно может стать «всегда сверху» без вашего ведома. Обновление до версии 7, чтобы исправить это
DuncanKinnear
источник
6
Это тоже мой опыт. Если есть одна вещь, в которой я уверен, это то, что вы делаете что-то не так, когда люди пытаются обойти вашу дружественность к пользователю и делать то, что они действительно хотят. Функциональность король.
ryvantage
Один из способов обойти это - разрешить открывать несколько JFrame с одинаковыми функциональными возможностями, но по умолчанию все выполняется в одном окне. Это фактически позволяет пользователю выбирать между SDI или MDI.
Гийом Поле
Сожалею? Можете ли вы объяснить свое решение немного лучше, пожалуйста? Как это может быть одно окно и несколько окон? У нас есть одно главное окно, в котором запускается основное приложение, но иногда нам нужно открывать диалоги, а иногда эти диалоги (в зависимости от требований пользователя) должны быть немодальными. Принятие правил, что интерфейс должен быть таким, или это просто выкопает большую дыру для себя.
DuncanKinnear
1
@GuillaumePolet Я согласен с Дунканом, можете ли вы объяснить, что вы имеете в виду немного больше? Я разделяю его замешательство
Ungeheuer
Я думаю, что он имеет в виду, что пользователь может запустить несколько копий приложения («JFrame»), но внутри каждого из них это SDI. Тем не менее, наше клиентское приложение является очень толстым клиентом, поэтому такой подход потребует ресурсов.
DuncanKinnear
20

Сделайте jInternalFrame в основной кадр и сделайте его невидимым. Затем вы можете использовать его для дальнейших событий.

jInternalFrame.setSize(300,150);
jInternalFrame.setVisible(true);
Вирандра Сингх Раторе
источник
19

Прошло много времени с тех пор, как я в последний раз касался свинга, но в целом это плохая практика. Некоторые из основных недостатков, которые приходят на ум:

  • Это дороже: вам придется выделять больше ресурсов для рисования JFrame, чем другие виды оконных контейнеров, такие как Dialog или JInternalFrame.

  • Не удобно для пользователя. Нелегко ориентироваться в куче JFrame, склеенных вместе, это будет выглядеть так, как будто ваше приложение является набором непоследовательных и плохо спроектированных приложений.

  • Использовать JInternalFrame просто. Это своего рода реторика, теперь это намного проще, и другие люди умнее (или с большим количеством свободного времени), чем мы уже продумали шаблон Desktop и JInternalFrame, поэтому я рекомендую использовать его.

Necronet
источник
7
Разве у вас не будет такого же эффекта для пользователя, когда вы используете несколько JInternalFrame? Лично я не согласен с использованием JInternalFrames! CardLayoutэто настоящее благословение!
Бранислав Лазич
4
Я согласен с @ brano88. JInternalFrameне дает никаких преимуществ ни в одном из трех упомянутых вами случаев (1. где доказательства, которые JInternalFrameлегче, чем JFrame? 2. ваши JInternalFrames могут быть столь же загроможденными / грязными / склеенными, как куча JFrames. 3. как JInternalFrameпроще? тот же самый точный код, за исключением того, что один содержится в a JDesktopPaneи один содержится в естественной области экрана. Они звучат для меня одинаково сложно.)
ryvantage
1
1. JFrame - это легкий компонент по сравнению с JInternalFrame, который является легковесным. 2. Вы когда-нибудь видели приложение, содержащее множество окон одновременно, чтобы оно работало? IDE, браузеры, даже в финансовом приложении это цель, чтобы держать его в том же объеме. 3. В прошлом я обнаружил, что JIF очень прост в использовании, и у меня нет претензий, конечно, выбрать компонент, который лучше всего подходит для сценария
Necronet,
4
1. Я хотел бы видеть доказательство этого. Оба являются объектами, оба являются объектами JComponents, оба имеют почти идентичные структуры, за исключением того, что один отображается на a, JDesktopа другой - нет. Опять извините, но я верю, что вы спекулируете относительно "веса" JFrame. 2. Мои приложения используют SDI, и мои клиенты очень довольны. Тем не менее, вы сказали «тонна окон», что, конечно, было бы плохо. Но моя точка зрения такова: "тонна" JInternalFrameбудет сосать так же плохо! Если вы говорите, что JIF-файлы позволяют вам быть небрежным дизайнером пользовательского интерфейса, то это ужасно. Беспорядок в беспорядке - беспорядок в беспорядке, будь то JF или JIF.
ryvantage
2
«Конечно, выберите компонент, который лучше всего подходит для сценария»
Некронет
10

Плохая практика определенно. Одна из причин заключается в том, что он не очень удобен для пользователя, поскольку каждый из них JFrameотображает новый значок на панели задач. Управление несколькими JFrameсекциями заставит вас рвать на себе волосы.

Лично я бы использовал ОДИН JFrameдля вашего вида приложений. Методы отображения нескольких вещей зависит от вас, их много. Canvasэс, JInternalFrame, CardLayoutдаже JPanelS возможно.

Несколько объектов JFrame = Боль, неприятности и проблемы.

Мэтт Доуси
источник
9
хм ... ничего нового по сравнению с принятым ответом, правда?
Клеопатра
5
«Каждый JFrame показывает новый значок на панели задач» - это относится только к Windows! В Mac OS X каждое приложение имеет только один значок док-станции, независимо от того, сколько окон у него открыто, и приложения обычно имеют несколько окон верхнего уровня.
Рольф
8

Я думаю, использование нескольких Jframes не очень хорошая идея.

Вместо этого мы можем использовать JPanelболее одного или более JPanelодинаковых JFrame.

Также мы можем переключаться между этим JPanelс. Так что это дает нам свободу отображать больше, чем вещи JFrame.

Для каждого JPanelмы можем создавать разные вещи, и все это JPanelможет отображаться по JFrameодному за раз.

Для переключения между этим JPanelами использования JMenuBarс JMenuItemsдля каждого JPanelили «JButton for eachJPanel`.

Больше, чем один JFrame, не очень хорошая практика, но нет ничего плохого, если мы хотим больше, чем один JFrame.

Но лучше изменить один JFrameдля наших различных потребностей, а не с несколькими JFrames.

Lijo
источник
5

Если фреймы будут одинакового размера, почему бы не создать фрейм и не передать фрейм в качестве ссылки на него.

Когда вы прошли кадр, вы можете решить, как его заполнить. Это было бы похоже на метод расчета среднего числа фигур. Будете ли вы создавать метод снова и снова?

Кейт Сприггс
источник
1
Это в основном делает то, что могут сделать Cardlayout и JTabbedPane, но делает это наоборот и делает ваш код слишком сложным, в то время как у вас есть чистое и простое решение для достижения того же самого.
Гийом Поле
4

Это не очень хорошая практика, но даже если вы хотите использовать ее, вы можете использовать шаблон синглтона в качестве ее хорошего. Я использовал одноэлементные шаблоны в большинстве моих проектов, это хорошо.

arunjoseph
источник
3
Синглтон-паттерн - это кошмар. Любой проект, который хочет масштабироваться, должен стараться избегать шаблона синглтона любой ценой.
Гийом Полет