O uso de vários JFrames: boas ou más práticas? [fechadas]

531

Estou desenvolvendo um aplicativo que exibe imagens e reproduz sons de um banco de dados. Estou tentando decidir se deve ou não usar um JFrame separado para adicionar imagens ao banco de dados da GUI.

Só estou me perguntando se é uma boa prática usar várias janelas do JFrame?

Mascate
fonte
11
Somente se você estiver direcionando uma configuração para vários monitores!
DNA
17
Eu também argumentaria que isso é independente da linguagem e tem a ver com a interface do usuário mais do que com o Java especificamente.
wchargin
6
Concordo com isso @WChargin Esta pergunta se tornou mais valiosa do que eu jamais pensei que poderia!
Peddler
1
Percebo que iniciantes (como eu) geralmente usam vários JFrames. Provavelmente porque é mais fácil chamá-lo de dentro do JFrame principal do que usar digamos um CardLayout. Embora em alguns casos não seja aconselhável usá-lo.
21113 Hoodlum
Depurar seria como comer cacto. Isso não é aconselhável.
Taslim Oseni

Respostas:

447

Só estou me perguntando se é uma boa prática usar vários JFrames?

Má prática (má, má).

  • Usuário não amigável: o usuário vê vários ícones na barra de tarefas ao esperar ver apenas um. Além dos efeitos colaterais dos problemas de codificação ..
  • Um pesadelo para codificar e manter:
    • Um diálogo modal oferece a oportunidade fácil de focar a atenção no conteúdo desse diálogo - escolha / corrija / cancele isso e prossiga. Vários quadros não.
    • Uma caixa de diálogo (ou barra de ferramentas flutuante) com um pai será exibida quando o pai for clicado - você teria que implementá-lo em quadros, se esse fosse o comportamento desejado.

Existem inúmeras maneiras de exibir muitos elementos em uma GUI, por exemplo:

  • CardLayout( demonstração curta ). Bom para:
    1. Mostrando assistente como diálogos.
    2. Exibindo seleções de lista, árvore etc. para itens que têm um componente associado.
    3. Alternando entre nenhum componente e componente visível.
  • JInternalFrame/JDesktopPane normalmente usado para um MDI .
  • JTabbedPane para grupos de componentes.
  • JSplitPane Uma maneira de exibir dois componentes cuja importância entre um ou outro (o tamanho) varia de acordo com o que o usuário está fazendo.
  • JLayeredPane muitos componentes bem ..layered.
  • JToolBarnormalmente contém grupos de ações ou controles. Pode ser arrastado pela GUI ou totalmente fora dela, de acordo com a necessidade do usuário. Como mencionado acima, será minimizado / restaurado de acordo com os pais que o fazem.
  • Como itens em um JList(exemplo simples abaixo).
  • Como nós em a JTree.
  • Layouts aninhados .

Mas se essas estratégias não funcionarem para um caso de uso específico, tente o seguinte. Estabeleça um único main e JFrame, em seguida, apareça JDialogou JOptionPaneinstâncias para o restante dos elementos flutuantes, usando o quadro como pai dos diálogos.

Muitas imagens

Nesse caso, onde os vários elementos são imagens, seria melhor usar um dos seguintes itens:

  1. Um único JLabel(centralizado em um painel de rolagem) para exibir a imagem em que o usuário estiver interessado naquele momento. Como visto em ImageViewer.
  2. Uma única linha JList. Como visto nesta resposta . A parte 'linha única' só funciona se tiverem as mesmas dimensões. Como alternativa, se você estiver preparado para dimensionar as imagens em tempo real, e elas terão a mesma proporção (por exemplo, 4: 3 ou 16: 9).

Andrew Thompson
fonte
4
@AndrewThompson Eu nunca me deparei com uma situação em que precisava de vários JFramesegundos antes e nunca considerei esses problemas, obrigado por explicar!
Jeffrey
4
@ user417896 "Apenas depende." Não, não faz. Eu usei o Gimp. É horrível e deve ser um MDI.
Andrew Thompson
4
@ryvantage "O Excel deve ser MDI?" Boa pergunta. Eu sinto que deve ser oferecido ao usuário nos dois sentidos (certamente não apenas na forma MDI). Por exemplo: 1) Atualmente, uso o TextPad e, por configuração à minha escolha, abre instâncias separadas, cada uma oferecendo vários documentos mostrados em uma lista. 2) Embora eu normalmente use FF no modo de guias, ocasionalmente arrasto uma guia para uma nova janela. - O fator comum nos exemplos é a escolha do usuário. Entregue o aplicativo. 'como o usuário quiser'.
Andrew Thompson
12
@AndrewThompson Você acabou de rebater seu próprio argumento com seu último comentário. Na sua resposta principal, você diz que isso é uma prática ruim e nunca deve ser feita, mas no seu comentário acima você diz que às vezes gosta de SDI e que devemos oferecer aos nossos usuários a opção. Certamente, é exatamente isso que o user417896 estava dizendo acima. Depende. Este é um dos meus maiores ódios de estimação sobre meus colegas desenvolvedores. O fato de muitos deles se tornarem religiosamente fanáticos pelas chamadas 'melhores práticas'. Não teríamos as UIs inovadoras que temos hoje, se todos seguíssemos as 'melhores práticas' e não pensássemos fora da praça.
DuncanKinnear
4
Generalização enorme! Não é sempre ruim permitir que o usuário controle suas janelas individualmente e acesse-as individualmente na barra de tarefas. A boa prática é estar ciente de todas as opções e escolher uma de forma inteligente. Certamente há casos em que vários JFrames fazem muito sentido.
Dawood ibn Kareem
203

A JFrameabordagem múltipla foi implementada desde que comecei a programar aplicativos Swing. Na maioria das vezes, eu fiz isso no começo porque não conhecia melhor. No entanto , à medida que amadureci em minha experiência e conhecimento como desenvolvedor e comecei a ler e absorver as opiniões de tantos desenvolvedores Java mais experientes on-line, tentei me afastar da JFrameabordagem múltipla (nos projetos atuais e nos projetos futuros ) apenas para encontrar ... obter essa ... resistência dos meus clientes! Quando comecei a implementar diálogos modais para controlar janelas "filho" JInternalFramees para componentes separados, meus clientes começaram a reclamar!Fiquei bastante surpreso, pois estava fazendo o que achava ser a melhor prática! Mas, como se costuma dizer, "uma esposa feliz é uma vida feliz". O mesmo vale para seus clientes. Obviamente, eu sou um contratado para que meus usuários finais tenham acesso direto a mim, o desenvolvedor, o que obviamente não é um cenário comum.

Então, vou explicar os benefícios da JFrameabordagem múltipla , bem como rebentar com os mitos, alguns dos contras que outros apresentaram.

  1. Máxima flexibilidade no layout - ao permitir JFrames separados , você oferece ao usuário final a capacidade de se espalhar e controlar o que está na tela dele. O conceito parece "aberto" e não restritivo. Você perde isso quando vai em direção a um grande JFramee um monte de JInternalFrames.
  2. Funciona bem para aplicativos muito modularizados - No meu caso, a maioria dos meus aplicativos possui de 3 a 5 grandes "módulos" que realmente não têm nada a ver um com o outro. Por exemplo, um módulo pode ser um painel de vendas e um pode ser um painel de contabilidade. Eles não falam um com o outro ou qualquer coisa. No entanto, o executivo pode querer abrir os dois, e o fato de serem quadros separados na barra de tarefas facilita sua vida.
  3. Facilita aos usuários finais fazer referência a materiais externos - Uma vez, eu tive a seguinte situação: Meu aplicativo tinha um "visualizador de dados", no qual você podia clicar em "Adicionar novo" e abriria uma tela de entrada de dados. Inicialmente, ambos eram JFrames. No entanto, eu queria que a tela de entrada de dados fosse JDialogcujo pai fosse o visualizador de dados. Fiz a alteração e imediatamente recebi uma ligação de um usuário final que confiava muito no fato de ele poder minimizar ou fechar o visualizador e manter o editor aberto enquanto ele referenciava outra parte do programa (ou site, eu não lembre-se). Ele não está em um monitor múltiplo, então ele precisava que a caixa de diálogo de entrada fosse a primeira e outra coisaser o segundo, com o visualizador de dados completamente oculto. Isso era impossível com um JDialoge certamente também seria impossível com um JInternalFrame. Eu relutantemente mudei de volta para ser separado JFramespor sua sanidade, mas isso me ensinou uma lição importante.
  4. Mito: Difícil de codificar - isso não é verdade na minha experiência. Não vejo por que seria mais fácil criar um JInternalFrameque um JFrame. De fato, na minha experiência, JInternalFramesofereço muito menos flexibilidade. Eu desenvolvi uma maneira sistemática de lidar com a abertura e o fechamento de JFrames nos meus aplicativos que realmente funcionam bem. Eu controlo o quadro quase completamente de dentro do próprio código do quadro; a criação do novo quadro, SwingWorkers que controlam a recuperação de dados nos encadeamentos em segundo plano e o código da GUI no EDT, restaurando / trazendo para a frente o quadro se o usuário tentar abri-lo duas vezes etc. Tudo o que você precisa para abrir meus JFrames é chamar um método estático público open()e o método aberto, combinado com umwindowClosing() O evento lida com o restante (o quadro já está aberto? Não está aberto, mas está carregando? etc.) Fiz essa abordagem como um modelo para que não seja difícil de implementar para cada quadro.
  5. Mito / Não Comprovado: Recurso Pesado - Gostaria de ver alguns fatos por trás dessa declaração especulativa. Embora, talvez, você possa dizer que um JFrameprecisa de mais espaço que um JInternalFrame, mesmo que você abra 100 JFrames, quantos recursos mais você realmente consumiria? Se sua preocupação é com vazamentos de memória devido a recursos: a chamada dispose()libera todos os recursos usados ​​pelo quadro para coleta de lixo (e, mais uma vez digo, um JInternalFramedeve chamar exatamente a mesma preocupação).

Escrevi muito e sinto que poderia escrever mais. De qualquer forma, espero não ser rebaixado simplesmente porque é uma opinião impopular. A pergunta é claramente valiosa e espero ter fornecido uma resposta valiosa, mesmo que não seja a opinião comum.

Um ótimo exemplo de vários quadros / documento único por quadro ( SDI ) versus quadro único / vários documentos por quadro ( MDI ) é o Microsoft Excel. Alguns dos benefícios do MDI:

  • é possível ter algumas janelas em formato não retangular - para não ocultar a área de trabalho ou outra janela de outro processo (por exemplo, navegador da web)
  • é possível abrir uma janela de outro processo em uma janela do Excel enquanto escreve na segunda janela do Excel - com o MDI, tentar escrever em uma das janelas internas dará foco a toda a janela do Excel, ocultando a janela de outro processo
  • é possível ter documentos diferentes em telas diferentes, o que é especialmente útil quando as telas não têm a mesma resolução

SDI (interface de documento único, ou seja, todas as janelas podem ter apenas um único documento):

insira a descrição da imagem aqui

MDI (Multiple-Document Interface, ou seja, todas as janelas podem ter vários documentos):

insira a descrição da imagem aqui

Ryvantage
fonte
16
Bem pensado. Se você possui vários módulos que nada têm a ver um com o outro, por que não criar aplicativos separados? Além disso, não há restrições dizendo que você precisa usar caixas de diálogo modais ; você pode usar caixas de diálogo sem modelo para servir como um segundo "quadro".
31413 Jeffrey
Resposta muito boa e resposta detalhada, embora eu deva concordar com o @kleopatra neste caso. Certa vez, tive um aplicativo com mais de cem telas em que os usuários queriam comparar dados de saída de várias telas / mesma tela com entradas diferentes. Criamos um sistema de janelas personalizado para nos permitir fazer isso. Os usuários eram apenas mais confortável com ter 2 JFrames para manter ao lado do outro;)
javatarz
Embora eu compreenda seu argumento, ainda assim eu preferiria ter tudo em um JFramee um grande pai JTabbedPane; mas com a possibilidade de abrir uma segunda janela (ou até mais) em que o layout possa ser diferente, oferecendo, portanto, um comportamento híbrido no qual os amantes de SDI são felizes e os de MDI também. Em todos os casos, sempre considerei JInternalFrameum padrão horrível que lhe dá todos os inconvenientes dos dois mundos. A flexibilidade que eles oferecem é uma porcaria e eles consomem muito espaço precioso na tela sem propósitos reais.
Guillaume Polet
Concordo que o SDI às vezes é apropriado (e os usuários costumam preferir). Há mais uma desvantagem, e eu não encontrei nenhuma solução alternativa para isso até agora, infelizmente: cada uma JFrametem seu próprio ícone na barra de tarefas. Às vezes é exatamente isso que você deseja, mas às vezes não é. No WinAPI, isso é fácil de configurar, mas no Swing parece que não pode ser feito.
Suma 27/03
@uma, nesse caso, acho que optaria por JDialogmais de um JFrame.
ryvantage
51

Eu gostaria de combater o argumento "não amigável" com um exemplo com o qual acabei de me envolver.

Em nossa aplicação, temos uma janela principal onde os usuários executam vários 'programas' como guias separadas. Tanto quanto possível, tentamos manter nosso aplicativo nessa única janela.

Um dos 'programas' executados apresenta uma lista de relatórios gerados pelo sistema, e o usuário pode clicar em um ícone em cada linha para abrir uma caixa de diálogo do visualizador de relatórios. Este visualizador está mostrando o equivalente às páginas A4 retrato / paisagem do relatório, para que os usuários gostem dessa janela como sendo bastante grande, quase preenchendo suas telas.

Alguns meses atrás, começamos a receber solicitações de nossos clientes para tornar essas janelas do visualizador de relatórios sem modelagem, para que eles pudessem ter vários relatórios abertos ao mesmo tempo.

Por algum tempo, resisti a esse pedido, pois não achei que fosse uma boa solução. No entanto, minha mente mudou quando descobri como os usuários estavam contornando essa 'deficiência' do nosso sistema.

Eles estavam abrindo um visualizador, usando o recurso 'Salvar como' para salvar o relatório como PDF em um diretório específico, usando o Acrobat Reader para abrir o arquivo PDF e, em seguida, fariam o mesmo no próximo relatório. Eles teriam vários leitores Acrobat sendo executados com as várias saídas de relatório que desejavam examinar.

Então, cedi e fiz com que o visualizador não fosse modelado. Isso significa que cada visualizador possui um ícone na barra de tarefas.

Quando a última versão foi lançada para eles na semana passada, a resposta esmagadora deles é que eles ADORAM. Esse foi um dos aprimoramentos recentes mais populares do sistema.

Então vá em frente e diga aos usuários que o que eles querem é ruim, mas, no final das contas, isso não fará nenhum favor a você.

ALGUMAS NOTAS:

  • Parece ser uma boa prática usar o JDialog para essas janelas sem modelagem
  • Use os construtores que usam o argumento novo ModalityTypee não o booleano modal. É isso que dá a essas caixas de diálogo o ícone da barra de tarefas.
  • Para diálogos sem modelo, passe um pai nulo para o construtor, mas localize-os em relação à janela 'pai'.
  • A versão 6 do Java no Windows possui um bug, o que significa que sua janela principal pode ficar 'sempre no topo' sem que você precise. Atualize para a versão 7 para corrigir isso
DuncanKinnear
fonte
6
Esta é exatamente a minha experiência também. Se há uma coisa de que tenho certeza, é que você está fazendo algo errado quando as pessoas tentam burlar a sua facilidade de uso para fazer o que realmente querem. A funcionalidade é rei.
ryvantage
Uma maneira de contornar isso é permitir a abertura de vários JFrame, todos oferecendo a mesma funcionalidade, mas, por padrão, tudo é feito em uma única janela. Na verdade, isso permite ao usuário escolher entre SDI ou MDI.
Guillaume Polet
Desculpa? Você pode explicar sua solução um pouco melhor, por favor? Como pode ser uma única janela E várias janelas? Temos uma janela principal na qual o aplicativo principal é executado, mas às vezes precisamos abrir caixas de diálogo e, às vezes, essas caixas de diálogo (com base nos requisitos do usuário) precisam ser sem modelo. Estabelecer regras para que a interface seja assim ou apenas abrirá um grande buraco para você.
precisa saber é o seguinte
1
@GuillaumePolet Concordo com Duncan, você pode explicar o que quer dizer um pouco mais? Eu compartilho sua confusão
Ungeheuer
Acho que o que ele quer dizer é que o usuário pode iniciar várias cópias do aplicativo (o 'JFrame'), mas dentro de cada um deles é SDI. No entanto, nosso aplicativo cliente é um cliente muito espesso, portanto, essa seria uma abordagem que requer muitos recursos.
DuncanKinnear
20

Faça um jInternalFrame no quadro principal e torne-o invisível. Então você pode usá-lo para outros eventos.

jInternalFrame.setSize(300,150);
jInternalFrame.setVisible(true);
Virendra Singh Rathore
fonte
19

Já faz um tempo desde a última vez que toco no swing, mas em geral é uma prática ruim fazer isso. Algumas das principais desvantagens que vêm à mente:

  • É mais caro: você terá que alocar muito mais recursos para desenhar um JFrame que outro tipo de contêiner de janela, como Dialog ou JInternalFrame.

  • Não é fácil de usar: não é fácil navegar para um monte de JFrame juntos, parecerá que seu aplicativo é um conjunto de aplicativos inconsistentes e com design inadequado.

  • É fácil usar o JInternalFrame Isso é meio retórico, agora é muito mais fácil e outras pessoas são mais inteligentes (ou com mais tempo livre) do que nós já pensamos no padrão Desktop e JInternalFrame, então eu recomendaria usá-lo.

Necronet
fonte
7
Você não tem o mesmo efeito para o usuário ao usar vários JInternalFrametambém? Pessoalmente, eu discordo do uso de JInternalFrame's! CardLayouté uma verdadeira benção!
Branislav Lazic
4
Eu concordo com @ brano88. JInternalFramenão oferece vantagens em nenhum dos três casos que você mencionou (1. onde está a evidência JInternalFramemais clara que JFrame? 2. Seus JInternalFrames podem ser tão confusos / bagunçados / presos como um monte de JFrames. 3. Como é JInternalFramemais fácil? mesmo código exato, exceto um está contido em um JDesktopPanee um é contido dentro da área da tela naturais soam igualmente complexas para mim)..
ryvantage
1
1. O JFrame é um componente de hevyweight comparado ao JInternalFrame, que é leve. 2. Você já viu um aplicativo que contém toneladas de janelas ao mesmo tempo funcionais? IDE, Navegadores, mesmo em aplicativos financeiros, é um objetivo mantê-lo no mesmo escopo. 3. Eu descobri JIF para ser muito fácil de usar no passado e não tenho nenhuma queixa é claro escolher o componente que melhor se adapte um cenário
Necronet
4
1. Gostaria de ver uma prova disso. Ambos são objetos, ambos são JComponents, ambos têm estruturas quase idênticas, exceto que um é renderizado em um JDesktope outro não. Mais uma vez, desculpe, mas acredito que você está especulando sobre o "peso" de JFrame. 2. Meus aplicativos usam SDI e meus clientes estão muito felizes. No entanto, você disse "uma tonelada de janelas", o que, é claro, seria péssimo. Mas, meu argumento é o seguinte: "uma tonelada de" JInternalFrames seria tão ruim quanto! Se você está dizendo que as JIFs permitem que você seja um designer de interface de usuário desleixado, isso é terrível. Uma bagunça desordenada é uma bagunça desorganizada, seja JF ou JIF.
ryvantage
2
"de pegar claro o componente que melhor combina com um cenário"
Necronet
10

Má prática definitivamente. Um dos motivos é que ele não é muito "fácil de usar", pois cada JFrameum mostra um novo ícone da barra de tarefas. Controlar vários JFrames fará com que você rasgue seu cabelo.

Pessoalmente, eu usaria o ONE JFramepara seu tipo de aplicativo. Métodos de exibição de várias coisas são com você, existem muitos. Canvases, JInternalFrame, CardLayout, mesmo JPanelé possivelmente.

Vários objetos JFrame = Dor, problemas e problemas.

Matt Dawsey
fonte
9
hmm ... nada de novo em comparação com a resposta aceita, afaics?
22413 kleopatra
5
"Todo JFrame mostra um novo ícone da barra de tarefas" - isso se aplica apenas ao Windows! No Mac OS X, todos os aplicativos têm apenas um ícone de encaixe, independentemente de quantas janelas foram abertas, e é comum que os aplicativos tenham várias janelas de nível superior.
Rolf
8

Eu acho que usar múltiplos Jframes não é uma boa ideia.

Em vez disso, podemos usar JPanels mais de um ou mais JPanelda mesma forma JFrame.

Também podemos alternar entre estes JPanels. Por isso, nos dá liberdade para exibir mais do que as coisas no JFrame.

Para cada um JPanel, podemos projetar coisas diferentes e tudo isso JPanelpode ser exibido em JFrameum único de cada vez.

Para alternar entre esta JPanels uso JMenuBarcom JMenuItemspara cada JPanelou 'JButton for eachJPanel`.

Mais de um JFramenão é uma boa prática, mas não há nada errado se queremos mais de um JFrame.

Mas é melhor mudar um JFramepara nossas diferentes necessidades, em vez de ter vários JFrames.

Lijo
fonte
5

Se os quadros tiverem o mesmo tamanho, por que não criar o quadro e passar o quadro como referência a ele?

Quando você passar o quadro, poderá decidir como preenchê-lo. Seria como ter um método para calcular a média de um conjunto de figuras. Você criaria o método repetidamente?

Keith Spriggs
fonte
1
Isso é basicamente fazer o que o Cardlayout e o JTabbedPane podem fazer, mas fazer isso de maneira inversa e tornar seu código excessivamente complexo enquanto você tem uma solução limpa e fácil para conseguir a mesma coisa.
Guillaume Polet
4

Não é uma boa prática, mas mesmo que você deseje usá-lo, pode usar o padrão singleton como bom. Eu usei os padrões singleton na maior parte do meu projeto, é bom.

arunjoseph
fonte
3
Padrão Singleton é um pesadelo. Qualquer projeto que queira escalar deve tentar evitar o padrão singleton a todo custo.
Guillaume Polet