Processen att utveckla ett enkelt GUI-program i Java. Skapa ett Java GUI Skapa ett Java GUI Application

Det grafiska gränssnittet i Java har gått igenom en mycket svår utvecklings- och bildningsväg. Han anklagades länge för långsamt arbete, girighet efter systemresurser och begränsad funktionalitet.

Java AWT

Suns första försök att skapa GUI det fanns ett bibliotek för java A.W.T.(Abstract Window Toolkit) - en verktygslåda för att arbeta med olika fönstermiljöer. Sun har gjort ett Java-lager som anropar metoder från bibliotek skrivna i C. AWT-biblioteksmetoderna skapar och använder de grafiska komponenterna i operativmiljön. Å ena sidan är detta bra, eftersom ett Java-program liknar andra program inom samma OS. Men när du kör det på en annan plattform kan det finnas skillnader i storlekarna på komponenter och teckensnitt som kommer att förstöra programmets utseende.

För att säkerställa flera plattformar A.W.T. komponentanropsgränssnitt har förenats, vilket resulterat i en något reducerad funktionalitet. Och uppsättningen av komponenter visade sig vara ganska liten. Till exempel finns det inga tabeller i AWT, och ikoner stöds inte i knappar. Dock paketet java.awt ingår med Java från den allra första utgåvan och kan användas för att skapa GUI.

Komponenterna alltså A.W.T. gör inget "jobb". Det är bara en "Java wrapper" för kontrollerna av det operativ system som de arbetar på. Alla förfrågningar till dessa komponenter omdirigeras till operativsystemet, som gör allt arbete.

Använda resurser A.W.T. försöker släppa automatiskt. Detta komplicerar arkitekturen något och påverkar prestandan. Att skriva något seriöst med AWT kommer att vara lite svårt. Nu används den bara för applets.

Grundläggande SWING-koncept

Efter A.W.T. Sun har utvecklat ett grafikkomponentbibliotek Gunga, skriven helt i Java. 2D används för rendering, vilket ger flera fördelar samtidigt. Uppsättningen av standardkomponenter överträffar vida AWT när det gäller variation och funktionalitet. Swing gör det enkelt att skapa nya komponenter genom att ärva från befintliga, och stöder en mängd olika stilar och skal.

Skapare av det nya UI-biblioteket Gunga"uppfann inte hjulet på nytt" och valde AWT som bas för sitt bibliotek. Naturligtvis talade vi inte om användningen av specifika tunga AWT-komponenter (representerade av knapp, etikett och liknande klasser). Endast lättviktskomponenter gav den erforderliga graden av flexibilitet och kontrollerbarhet. Arvsdiagrammet visar förhållandet mellan AWT och Swing.

Den viktigaste skillnaden Gunga från AWT är att Swing-komponenter inte alls är anslutna till operativsystemet och är därför mycket stabilare och snabbare. Sådana komponenter kallas lätta i Java, och att förstå de grundläggande principerna för hur de fungerar kommer att räcka långt för att förklara hur Swing fungerar.

Swing Top Level Containers

För att skapa ett programs grafiska gränssnitt måste du använda speciella komponenter i Swing-biblioteket, så kallade toppnivåbehållare. De är operativsystemfönster som är värd för användargränssnittskomponenter. Behållare på toppnivå inkluderar JFrame- och JWindow-fönstren, JDialog-dialogrutan och JApplet-appleten (som inte är ett fönster, men är också avsedd att visa ett gränssnitt i webbläsaren som kör denna applet). Swingcontainrar på toppnivå är tunga komponenter och är ett undantag från den allmänna regeln. Alla andra Swing-komponenter är lätta.

Enkel Gunga exempel på fönstergränssnitt jFrame.

Importera java.awt.Dimension; importera javax.swing.JFrame; importera javax.swing.JLabel; public class JFrameTest ( public static void createGUI() ( JFrame frame = new JFrame("Test frame"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JLabel label = new JLabel("Test label"); frame.getContentPane(). add(label); frame.setPreferredSize(new Dimension(200, 100)); frame.pack(); frame.setVisible(true); ) public static void main(String args) ( JFrame.setDefaultLookAndFeelDecorated(true); javax. swing.SwingUtilities.invokeLater(new Runnable() ( public void run() ( createGUI(); ) )); ) )

Konstruktör JFrame() utan parametrar skapar ett tomt fönster. Konstruktör JFrame(Strängtitel) skapar ett tomt fönster med titeltitel. Att skapa det enklaste programmet med ett tomt fönster måste följande metoder användas:

  • setSize(int width, int height) - definierar storleken på fönstret;
  • setDefaultCloseOperation(int operation) - definition av åtgärd vid programavslutning;
  • setVisible(boolean synlig) - gör fönstret synligt.

Om du inte anger storleken på fönstret kommer det att ha en nollhöjd oavsett vad som finns i det. Fönstrets dimensioner inkluderar inte bara "arbetsområdet", utan också kanterna och titelraden.

Metoden setDefaultCloseOperation definierar åtgärden som ska vidtas när programmet avslutas. För att göra detta, skicka konstanten EXIT_ON_CLOSE, som beskrivs i klassen JFrame, som operationsparameter.

Som standard skapas fönstret osynligt. För att visa fönstret på skärmen anropas metoden setVisible med parametern true. Om du anropar den med den falska parametern kommer fönstret att bli osynligt.

GUI java swing exempel på att skapa fönster jFrame visas i följande figur.

För att ansluta biblioteket Gunga applikationen måste importera biblioteket javax.swing.

Varje gång en behållare på toppnivå skapas, oavsett om det är ett vanligt fönster, dialogruta eller applet, skapar behållarens konstruktor JRootPane rotpanel. Swing-behållare på toppnivå ser till att andra komponenter inte kan "krypa" utanför JRootPane.

Rot blek JRootPane lägger till en "djup"-egenskap till behållare, vilket ger möjlighet att inte bara placera komponenter ovanför varandra, utan även, om nödvändigt, byta ut dem, öka eller minska djupet på komponenterna. Denna funktion är nödvändig när du skapar ett program för flera dokument. Gunga, vars fönster representerar lätta komponenter staplade ovanpå varandra, samt rullgardinsmenyer (sammanhang) och verktygstips.

Följande bild visar tydligt strukturen på rotpanelen JRootPane.

Rotpanel JRootPaneär en behållare som ärver från basklassen Swing JComponent. I den här behållaren är en speciell layouthanterare, implementerad i den interna RootPaneLayout-klassen, ansvarig för layouten av komponenterna. Denna layouthanterare är ansvarig för att se till att alla komponenter i rotpanelen är placerade som de ska: den skiktade panelen upptar hela utrymmet i fönstret; dess FRAME_CONTENT_LAYER innehåller menyraden och innehållspanelen, och framför allt är det en transparent panel.

Alla komponenter i rotpanelen JRootPane kan erhållas eller ändras. Den har en uppsättning get/set-metoder för detta. Programmässigt JRootPane kan erhållas med metoden getRootPane() .

Förutom behållare på toppnivå, används rotpanelen i interna JInternalFrame-fönster skapade i multidokumentapplikationer och placerade på "skrivbordsskivan" JDesktopPane. Detta gör att du kan glömma att dessa fönster är vanliga lättviktskomponenter och arbeta med dem som om de vore riktiga behållare på högsta nivå.

Layered Panel JLayeredPane

Vid basen av rotpanelen (behållaren) ligger den så kallade skiktade panelen JLayeredPane En som tar upp allt tillgängligt utrymme i behållaren. Det är i denna panel som alla andra delar av rotpanelen finns, inklusive alla användargränssnittskomponenter.

JLayeredPane används för att lägga till en djupegenskap till behållaren. Det vill säga, flerskiktspanelen låter dig organisera en tredje dimension i behållaren, längs vilken komponentens lager (lager) är placerade. I en normal behållare bestäms platsen för en komponent av en rektangel som visar hur mycket av behållaren komponenten upptar. När du lägger till en komponent till en flerskiktspanel måste du ange inte bara rektangeln som komponenten upptar, utan också lagret där den kommer att placeras. Ett lager i en skiktad panel definieras av ett heltal. Ju större nummer som definierar lagret, desto högre är lagret.

Den första komponenten som läggs till behållaren är högre än de komponenter som läggs till senare. Oftast hanterar utvecklaren inte komponenternas positioner. När du lägger till komponenter ändras deras position automatiskt. Den skiktade panelen låter dig dock ändra placeringen av komponenterna dynamiskt efter att de har lagts till i behållaren.

Skiktade panelfunktioner används i stor utsträckning av vissa komponenter Gunga. De är särskilt viktiga för flerdokumentapplikationer, verktygstips och menyer. Multidokument Gunga applikationer använder en speciell behållare JDesktopPane("skrivbord") ärvt från JLayeredPane En som håller inre Svängfönster. De viktigaste funktionerna i en multidokumentapplikation - att placera det "aktiva" fönstret ovanför andra, minimera fönster, dra dem - tillhandahålls av mekanismerna i den skiktade panelen. Den största fördelen med att använda en skiktad panel för verktygstips och menyer är deras hastighet. Istället för att skapa ett nytt tungviktsfönster för varje verktygstips eller meny, placerat ovanför komponenten där verktygstipset eller menyn begärdes, Gunga skapar en snabb lättviktskomponent. Denna komponent placeras i ett tillräckligt högt lager av den skiktade panelen ovanför i stapeln av alla andra komponenter och används för att visa ett verktygstips eller meny.

Flerskiktspanelen låter dig organisera ett obegränsat antal lager. Strukturera JLayeredPane innehåller flera standardlager, som används av alla Swing-komponenter, vilket säkerställer att alla mekanismer för den skiktade panelen fungerar korrekt. Standard JLayeredPane-lager visas i följande figur.

Standardlagret används för att vara värd för alla normala komponenter som läggs till i behållaren. Det här lagret innehåller de interna fönstren för program för flera dokument.

Palettlagret är utformat för att vara värd för fönster med en uppsättning verktyg, som vanligtvis överlappar resten av gränssnittet. Panelen JDesktopPane låter dig skapa sådana fönster, som placerar dem på det här lagret.

Modallagret var avsett att vara värd för lätta modala dialogrutor. Sådana dialogrutor är dock inte implementerade ännu, så detta lager används för närvarande inte i Swing.

Det vanligaste lagret för popup-menyer och verktygstips.

Det översta lagret. Avsedd för dra och släpp-operationer ( dra och släpp drop), som ska vara tydligt synlig i programgränssnittet.

Ett litet exempel på en JLayeredPane med en lagerpanel visar hur man lägger till komponenter i olika lager och hur lagren staplas ovanpå varandra:

Importera javax.swing.*; importera java.awt.*; // klass för att rita två typer av figurer med textklass Figur utökar JComponent ( private static final long serialVersionUID = 1L; private Color color; private int type; private String text; // parametrar: färg och figurtyp Figure(Color color, int) typ, String text) ( this.color = color; this.type = type; this.text = text; setOpaque(false); ) public void paintComponent(Graphics g) ( // rita figuren g.setColor(color); switch (typ ) ( fall 0: g.fillOval(0, 0, 90, 90); break; fall 1: g.fillRect(0, 0, 130, 80); break; ) g.setColor(Color.yellow) ; g. drawString(text, 10, 35); ) ) public class JLayeredPaneTest utökar JFrame (privat statisk slutlig lång serialVersionUID = 1L; public JLayeredPaneTest() ( // create window super("Exempel LayeredTest"); // avsluta när fönster är stängd setDefaultCloseOperation( EXIT_ON_CLOSE); // definiera lagerpanel JLayeredPane lp = getLayeredPane(); // skapa tre former Figur figur1 = ny Figur(Color.red , 0, "Figur po valp"); Figur figur2 = ny figur(Color.blue, 0, "Figur 1"); Figur figur3 = ny figur(Color.cyan, 1, "Figur 2"); // bestäm platsen för figurerna i fönstret figure1.setBounds(10, 40, 120, 120); figure2.setBounds(60, 120, 160, 180); figur3.setBounds(90, 55, 250, 180); // lägga till former till olika lager lp.add(figur1, JLayeredPane.POPUP_LAYER); lp.add(figur2, JLayeredPane.PALETTE_LAYER); lp.add(figur3, JLayeredPane.PALETTE_LAYER); // ändra positionen för en av figurerna lp.setPosition(figur3, 0); // bestämma storleken och öppna fönstret setSize(280, 250); setVisible(true); ) public static void main(String args) ( JFrame.setDefaultLookAndFeelDecorated(true); new JLayeredPaneTest(); ) )

Exemplet skapar ett litet fönster jFrame och flera figurkomponenter läggs till den skiktade panelen. För att få en skiktad panel i valfri Swing-behållare på toppnivå, ring bara metoden getLayeredPane().

Figurhjälparklassen ärver egenskaperna hos basklassen JComponent och låter dig rita två typer av former (cirklar och rektanglar) med olika färger. Parametrar för att rita former ställs in i klasskonstruktorn.

När du definierar ett gränssnitt skapas tre former av olika färger (två cirklar och en rektangel). Cirkeln placeras i lagret POPUP_LAYER och rektanglarna placeras i lagret PALETTE_LAYER. Vid placering av komponenter anges deras absoluta skärmkoordinater, eftersom de vanliga platshanterarna inte fungerar i en skiktad panel.

I slutet ändras positionen för en av rektanglarna så att den är den första i lagret, även om den ursprungligen lades till den andra. När du kör applikationen ser du att den skiktade panelen fungerar och ordnar komponenterna snyggt efter deras lager och positioner.

I konventionella applikationer används den skiktade panelen sällan direkt, där den utför sina funktioner osynligt. Men ibland hjälper det att skapa fantastiska effekter och ovanliga gränssnitt, till exempel så att du kan placera animationer eller video ovanpå vanliga komponenter utan att kräva omänskliga ansträngningar och tricks från utvecklaren.

ContentPane

ContentPane är nästa del av rotpanelen och används för att vara värd för programmets användargränssnittskomponenter. ContentPane upptar det mesta av utrymmet på den skiktade panelen (förutom utrymmet som upptas av menyraden). För att förhindra att innehållspanelen täcker komponenter som sedan läggs till i fönstret, placerar den skiktade panelen den på ett speciellt mycket lågt lager som heter FRAME_CONTENT_LAYER, numrerat -30000.

Du kan komma åt innehållspanelen med getContentPane() JFrame klass. Med hjälp av add(Component component)-metoden kan du lägga till vilken kontroll som helst till den. Byta ut ContentPane någon annan panel av JPanel-typ, kan du använda metoden setContentPane()

Ett exempel på att lägga till en knapp i innehållspanelen:

JButton newButton = new JButton(); getContentPane().add(newButton);

Som ett resultat får vi ett fönster med en knapp. Knappen upptar hela det tillgängliga området i fönstret. Denna effekt är inte användbar i alla program, så du måste använda olika sätt för att ordna element på panelen.

Innehållspanelen kan bytas ut helt. Tänk på följande Gunga exempel på innehållspanel ContentPane.

Importera javax.swing.*; public class ContentPaneReplace utökar JFrame (privat statisk slutlig lång serialVersionUID = 1L; public ContentPaneReplace() (super("Test ContentPane"); setDefaultCloseOperation(EXIT_ON_CLOSE); // Skapa en panel med två knappar JPanel contents = new JPanel(); contents. add (new JButton("Familj")); contents.add(new JButton("Skola")); // Ersätter innehållsrutan setContentPane(contents); // Fastställande av storleken på fönstret setSize(200, 100); // Öppnar fönstret setVisible (true); ) public static void main(String args) ( JFrame.setDefaultLookAndFeelDecorated(true); new ContentPaneAdd(); ) )

Exemplet skapar ett litet fönster och en panel med två knappar, vilket är sedan setContentPane() ersätter fönstrets innehållsruta. Således användes en ersättning istället för en enklare tillägg - anropande add ()-metoden. Fönstergränssnittet visas i följande skärmdump.

Innehållspanel ContentPane i sig är inget speciellt. Du behöver bara komma ihåg att komponenterna läggs till den.

Transparent JOptionPane

Transparent panel JOptionPane placeras som rotpanelen ovanför alla element i den skiktade panelen. Placeringen av JOptionPane hanteras av rotrutan, som placerar den genomskinliga rutan ovanför den skiktade rutan så att den helt täcker hela fönsterområdet, inklusive området som upptas av menyraden.

JOptionPane används sällan i applikationer, så som standard gör rotpanelen den osynlig, vilket minskar belastningen på ritsystemet. Tänk på att om du gör en genomskinlig panel synlig måste du vara säker på att den är transparent (dess ogenomskinliga egenskap är falsk), annars kommer den att täcka alla andra element i rotpanelen och resten av gränssnittet kommer att vara osynligt.

I vilka fall kan en transparent panel användas? JOptionPane? Den kan användas för att definiera applikationsfunktioner som skulle kräva betydande ansträngning att implementera från grunden. Den transparenta panelen kan anpassas för automatisk testning av användargränssnitt. Händelserna som syntetiseras i den låter dig spåra mellanliggande felsökningsresultat. Ibland är detta tillvägagångssätt mycket effektivare än manuell testning.

Transparent panel JOptionPane kan användas för att skapa en snygg animation som "svävar" ovanpå alla komponenter, inklusive menyraden, eller för att fånga händelser om några av dem behöver hanteras innan de skickas till huvudgränssnittet.

Ett exempel på att använda en transparent Swing JOptionPane:

// Användning transparent panel JOptionPane importera java.awt.Dimension; importera java.awt.Font; importera java.awt.event.WindowEvent; importera java.awt.event.WindowListener; importera javax.swing.JDialog; importera javax.swing.JFrame; importera javax.swing.JLabel; importera javax.swing.JOptionPane; importera javax.swing.UIManager; public class JOptionPaneTest utökar JFrame (privat static final long serialVersionUID = 1L; public static final Font FONT = new Font("Verdana", Font.PLAIN, 11); public static void createGUI() ( JFrame frame = new JFrame("Test JOptionPane "); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.addWindowListener(new WindowListener() ( public void windowActivated(WindowEvent-händelse) () public void windowClosed(WindowEvent-händelse) () public void-fönsterDeaktiverad(window) public void-händelse (fönster) windowDeiconified(WindowEvent event) () public void windowIconified(WindowEvent event) () public void windowOpened(WindowEvent event) () public void windowClosing(WindowEvent event) ( Objektalternativ = ( "Ja", "Nej!" ); int rc = JOptionPane.showOptionDialog(event.getWindow(), "Stäng fönster?", "Confirm", JOptionPane.YES_NO_OPTION, JOptionPane.QUESTION_MESSAGE, null, options, options); (false);System.exit(0); ) ) )); JLabel label = new JLabel("Använd transparent panel när du stänger fönstret"); frame.getContentPane().add(label); frame.setPreferredSize(ny dimension(350, 80)); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); ) public static void main(String args) ( javax.swing.SwingUtilities.invokeLater(new Runnable() ( public void run() ( UIManager.put("Button.font", FONT); UIManager.put("Label.font ", FONT); JFrame.setDefaultLookAndFeelDecorated(true); JDialog.setDefaultLookAndFeelDecorated(true); createGUI(); ) )); ) )

Om metoden setDefaultCloseOperation skickas en konstant JFrame.EXIT_ON_CLOSE, när fönstret stängs slutar programmet att fungera. I exemplet skickas en konstant till denna metod JFrame.DO_NOTHING_ON_CLOSE så att inget händer när fönstret stängs. Att avsluta applikationen i exemplet görs från JFrame-lyssnaren WindowListener i metoden fönster stängs. När fönstret stängs anropas metoden windowClosing med en WindowEvent-händelseparameter, som i en transparent Swing JOptionPane öppnar en bekräftelsedialog.

Följande skärmdump visar två programfönster. Översta huvudfönstret. Om du stänger det här fönstret öppnas den nedre dialogrutan för bekräftelse av avsikt.

JMenuBar menyraden

En av de viktiga funktionerna med att använda JRootPanes rotpanel i Swing är behovet av att placera en menyrad i fönstret. JMenuBar. En seriös applikation kan inte byggas utan någon form av meny för åtkomst till programmets funktioner. Swing-biblioteket ger utmärkta faciliteter för att skapa bekväma JMenuBars som också är lätta komponenter.

Menyfältet JMenuBar placeras i en skiktad panel i ett speciellt lager FRAME_CONTENT_LAYER och upptar ett litet utrymme överst i fönstret. Längden på menyraden är lika med fönstrets storlek. Menyradens bredd beror på komponenterna den innehåller.

Rotpanelen ser till att innehållspanelen och menyraden JMenuBaröverlappade inte. Om menyraden inte krävs använder rotpanelen allt utrymme för att rymma innehållspanelen.

Swing exempel

Källkoderna för de exempel som diskuteras i texten på sidan kan laddas ner.

I den här korta artikeln vill jag beskriva processen att skapa ett litet program som stöder GUI på språket Java. Det förutsätts att läsaren är bekant med språkets grunder. Java.

Och så, vilka verktyg behöver vi:

  • Java Virtual Machine (OpenJDK eller Oracle JDK)
  • Intellij IDEA (eller annan IDE för Java)

Efter installation nödvändig programvara, öppna IntelliJ IDÉ och skapa ett nytt projekt: Arkiv -> Nytt projekt...

Jag döpte projektet guiBase. Som du kan se på skärmdumpen, mappen src innehåller ingenting, så vi skapar i den vår huvudklass som innehåller funktionen huvud.

Public class Main ( public static void main(String args) ( System.out.println("Hej, Govzalla!"); ) )

Se innehållet i huvudklassen ovan. Vi kan nu skapa ett projekt ( Byggprojekt ) och kör den ( Springa ). Nere i terminalen på din ID du kommer att se ett meddelande Hej, Govzalla!. Men som du själv förstått - det stöder inte GUI.

I det här skedet har vi redan ett fungerande program, men utan stöd för GUI. Och nu i samma mapp src skapa GUI-formulär: Nytt -> GUI-formulär

Öppna det skapade GUI-formuläret, klicka på jPanel och ställ in dess identifierare i fältet fält namn, Jag frågade panel.

Dra och släpp sedan till formuläret på höger sida JTextField, JPasswordField och JButton:

Det återstår att lägga till koden och länka vårt formulär till den. När vi lade till formuläret huvudfönstret, skapades klassen automatiskt huvudfönstret, denna klass är klassen för den genererade formen, dvs. denna klass kommer att betjäna alla evenemang i den angivna formen.

Även om vår fönsterklass innehåller de nödvändiga elementen, har den inte ens nu något att göra med GUI, så låt oss utöka det med jFrame och ärver alla grundläggande och nödvändiga funktioner i GUI .

Vi har för närvarande formuläret huvudfönstret och klass huvudfönstret utökas med jFrame. Nu måste vi definiera alla tillagda GUI-element som klassinnehåll huvudfönstret this.getContentPane().add(panel); Därefter kommer innehållet i filen MainWindow.java att ändras enligt följande:

Importera javax.swing.*; public class MainWindow utökar JFrame (privat JTextField textField1; private JPasswordField passwordField1; private JButton button1; private JPanel panel; public MainWindow() ( this.getContentPane().add(panel); ) )

Om du försöker köra koden kommer du att se samma "Hej, Govzalla!"-meddelande igen. Saken är att vi skapade en klass och formuläret till den, men skapade inte en instans av den här klassen.

Det är dags att ändra filen Main.java och lägga till koden för att skapa vårt GUI där:

Importera java.awt.*; public class Main ( public static void main(String args) ( // Skapa en instans av MainWindow-klassen MainWindow mainWindow = new MainWindow(); // Packa alla element från vårt formulär mainWindow.pack(); // Ändra storlek på fönstret mainWindow.setSize( new Dimension(200, 200)); // Visa det skapade fönstret mainWindow. setVisible(true); ) )

Kör koden

Genom att klicka på knappen kommer du att märka att programmet inte reagerar på något sätt. Saken är den att vi inte har lagt till lyssnaren än ( Lyssnare) för evenemang ( evenemang) på knappen.

händelselyssnare ( evenemangslyssnare) JButton måste vara en adapterimplementering ActionListener, så lägg till följande kod i klassens brödtext huvudfönstret:

Privatklass MyButtonListener implementerar ActionListener ( @Override public void actionPerformed(ActionEvent actionEvent) ( ) )

Metod åtgärdUtförd() kommer att hantera alla button1 button-händelser, men först måste du fortfarande berätta för button1 vilken klass den kommer att hantera, så lägg till följande kod till MainWindow-klasskonstruktorn: this.button1.addActionListener(new MyButtonListener()); Så att vår hanterare inte är meningslös, lägg till följande kod till metoden åtgärdUtförd():

@Override public void actionPerformed(ActionEvent actionEvent) ( if (textField1.getText().equals(passwordField1.getText())) ( JOptionPane.showMessageDialog(null, "Success"); ) else ( JOptionPane.showMessageDialog, "Fail( "); ) )

Nu kommer programmet att svara korrekt på händelser, inte på alla händelser, förstås. Om du till exempel försöker inaktivera programmet genom att klicka på krysset försvinner fönstret, men programmet kommer fortfarande att fungera, eftersom. huvudfönstrets händelsehanterare har inte lagts till.

Beskrivning av presentationen Skapande av ett grafiskt gränssnitt i Java Graphic-bibliotek med bilder

Java Graphical Libraries Java har följande paket för att skapa grafiska gränssnitt: Abstrakt Windows Toolkit (AWT) - kommer med JDK, varje AWT-komponent har sin egen visuella komponent (peer) för ett visst operativsystem, portabilitet tillhandahålls av java-paketet. awt. jämlikar; uppsättningen grafiska komponenter är begränsad; utseende beror på operativsystemet. Standard Widget Toolkit (SWT) - levereras separat för specifika operativsystem, som ingår i Eclipce-miljön, interagerar med operativsystemet med hjälp av peer-gränssnitt, till skillnad från AWT har utbudet av komponenter utökats. Swing - kommer med JDK, utökar AWT-klasser, är inte beroende av OS peer-komponenter. Java 3 D - tredimensionell grafik.

Tungvikts- och lättviktskomponenter Tungviktskomponenter – Återgivna av operativsystemet – De flesta AWT-komponenter Lätta (ligntvikts) komponenter – Återgiven med java-kod – Alla Swing-komponenter utom fönster på toppnivå (applikationsfönster) Tungviktskomponenter ritas alltid ovanpå lätta.

Model-View-Controller (MVC)-arkitektur MVC-designmönstret separerar applikationsdata, användargränssnitt och kontrolllogik i tre separata komponenter – modell, vy och styrenhet – så att varje komponent kan modifieras oberoende. Modellen (modellen) lagrar data för komponenten och gör det enkelt, utan att hänvisa till själva komponenten, att ändra eller ta emot denna data. Visa (visa) visar data på skärmen för presentation för användaren. Kontrollören bestämmer hur modellens syn och data ska reagera som svar på användaråtgärder.

Fördelar med MVC Du kan bifoga flera vyer till samma modell utan att påverka implementeringen av modellen. Till exempel kan vissa data presenteras i ett kalkylblad, ett stapeldiagram och ett cirkeldiagram samtidigt. Utan att påverka implementeringen av vyer kan du ändra reaktionerna på användaråtgärder (klicka på en knapp, ange data), för detta räcker det att använda en annan styrenhet. Ett antal utvecklare specialiserar sig på endast ett av områdena: antingen att utveckla ett grafiskt gränssnitt eller att utveckla affärslogik. Därför är det möjligt att säkerställa att programmerare som är involverade i utvecklingen av affärslogik (modell) inte kommer att vara medvetna om vilken representation som kommer att användas överhuvudtaget.

Interaktioner mellan modell, vy och styrenhet Klassisk modell Ett nära förhållande mellan styrenhet och modell och styrenhet och vy. En vy (vy) är associerad med en enda kontrollenhet och varje kontrollenhet med en enda vy. View och Controller har en direktlänk till modellen.

MVC exempel public class Model (privat int int. Array = (1, 2, 3, 4, 5); public String get. String. Array() (retur "int. Array=" + Arrays. till. String(int. Array); ) public void set.Int.Array(int index, int value) (this.int.Array = värde; ) ) public class Controller ( Model model = new Model(); visa vy= ny vy(); Controller()( uppdatering. View(); ) void set. Array. Värde(int index, int värde) (modell. set. Int. Array(index, värde); update. View(); ) ogiltig uppdatering. View() ( view. show. Array(modell. get. String. Array()); ) ) public class View ( public void show. Array(String array. String)( System. out. println("View"); System.out.println(array.String); System.out.println(); ) ) public class User ( public statc void main(String args) ( Controller controller = new Controller(); controller.set.Array.Value( fjorton); ) )

Swing-modellen förenklar implementeringen. Modellen vet inte vilken UI-representant den samarbetar med eller vilken komponent som använder den sätter utseendet och känslan för alla bibliotekskomponenter kommunicerar med modellen endast genom komponentklassen. Kontrollervyn hanterar användarhändelser och ritar komponenten på skärmen. Knappar, listor, tabeller, textfält...

Knapp för gränssnittskomponenter — knapp; JCheck. Ruta - kryssruta; jCombo. Box - rullgardinslista; JLabel - etikett, inskription; jList - lista; JPassword. Fält - textfält för dold inmatning; JProgress. Bar - en komponent för att visa ett nummer i ett visst intervall; JRadio. Knapp - omkopplare, radioknappar, används vanligtvis med knappkomponenten. grupp; JSlider - en komponent som låter dig välja ett värde från ett givet intervall; JTable - tabell; jtext. Fält är ett textfält på en rad; jtext. Area är ett textfält med flera rader; JTree är ett träd.

Gränssnittsbehållare Delar av användargränssnittet som innehåller andra komponenter Behållare på toppnivå: Frame, JFrame - programfönster; JDialog - applikationsdialog; jColor. Väljare - dialogruta för färgval; jfile. Väljare - dialogruta för att välja filer och kataloger; fil. Dialog - dialog för att välja filer och kataloger (awt-komponent). Enkla behållare: JPanel - en enkel panel för att gruppera element, inklusive kapslade paneler; jTool. Bar - verktygsfält (vanligtvis knappar); jscroll. Panel - en rullningslist som låter dig rulla innehållet i ett underordnat element; JDesktop. Panel - en behållare för att skapa ett virtuellt skrivbord eller applikationer baserade på MDI (multple-document interface); JEditor. Panel , JText. Panel - behållare för att visa ett komplext dokument som HTML eller RTF; JTabbad. Panel - en behållare för att hantera bokmärken;

Skapa en fönsterimport-java. awt. *; klass också. enkel. Frame extends Frame( public statc void main(String args)( Frame fr = new Too. Simple. Frame(); fr. set. Size(400, 150); // window size fr. set. Visible(true); / /render window) // stängningsknappen fungerar inte) Sväng

Fönster med anpassad ikon import javax. gunga. *; ram i offentlig klass. Stängning förlänger JFrame ( public Frame. Closing() ( super("Window Title"); // operation vid stängning av fönsteruppsättningen. Standard. Close. Operaton(EXIT_ON_CLOSE); // när du stänger fönstret, avsluta //-ikonen för fönsteruppsättning. Icon.Image(get. Toolkit(). get. Image("ikon. gif")); // C: / icons / icon. png // displayuppsättning. Storlek(300, 100); // fönster storlek bredd och höjd set.Visible(true); // render window ) public statc void main(String args) ( new Frame.Closing(); ) ) Swing

Standarddialogrutor Dialogruta Typ Beskrivning NFORMATION_MESSAGE Dialogrutan Visar allmän information med ikon av lämplig typ WARNING_MESSAGE Dialogruta Visar varningsinformation med ikon av lämplig typ QUESTION_MESSAGE Dialogruta för frågor för inmatning av information ERROR_MESSAGE Dialogruta Visar felinformation med ikon av lämplig_typ M PLAIN av lämplig typ PLAIN att dialogrutan inte tillhör någon av ovanstående typer. Visas på skärmen utan en standardikon. Dialogrutor kan vara modala eller modelllösa Dialogrutor kan vara modala (fokusera på fönstret tills knappen trycks in) eller modelllösa

Inmatnings- och meddelandefönster importerar java. awt. *; importera javax. gunga. *; public class Soluton ( public static void main(String args) ( JOpton. Pane. show. Message. Dialog(null , "Hello, World"); String s = JOpton. Panel. show. Input. Dialog("Ange ditt namn" ); ) ) Gunga

Standard Java-layouter 1. Kantlayout. Layout (polär placering). 2. Flödeskompositör. Layout (konsekutiv placering). 3. Länkare. Rutnät. Layout (bordslayout). 4. Fjäderlänk. Layout (relativ placering). 5. Boxlinker. Layout (blockplacering).

Polar Layout (Border.Layout layout) Border.Layout värde. Layout. NORTH eller strängen "North" - komponenten ligger längs fönstrets övre (norra) gräns och sträcker sig till hela dess bredd. Det är vanligtvis där verktygsfältet finns. Gränsvärde. Layout. SÖDER eller strängen "Söder" - komponenten ligger längs den nedre (södra) gränsen och sträcker sig till fönstrets fulla bredd. Denna position är idealisk för statusfältet. Gränsvärde. Layout. WEST eller strängen "West" - komponenten ligger längs fönstrets vänstra (västra) gräns och sträcker sig till hela sin höjd, men storleken på de norra och södra komponenterna beaktas (de har prioritet). Gränsvärde. Layout. EAST eller strängen "East" - komponenten är placerad längs den högra (östliga) kanten av fönstret. Annars liknar dess placering den västra komponenten. Gränsvärde. Layout. CENTER eller raden "Center" - komponenten placeras i mitten av fönstret och tar upp största möjliga utrymme.

Ett exempel på användning av Border-layouten. Layout import javax. gunga. *; importera java. awt. *; offentlig klass Border. Layout. Sample utökar JFrame ( public Border. Layout. Sample() ( super("Border. Layout. Sample"); set. Size(400, 300); set. Standard. Close. Operaton(EXIT_ON_CLOSE); // hämta klassinnehållsrutan JFrame Container c = get.Content.Pane(); // Som standard använder Swing Border.Layout-hanteraren // lägg till komponenter till panelen med hjälp av strängkonstanter c. add(new JButton("North"), "North") ; c. add(new JButton("South"), "South"); // eller konstanter från klassen Border. Layout // JLabel-element för att visa text c. add(new JLabel("West"), Border. Layout. WEST); c. add(new JLabel("East"), Border. Layout. EAST); // om parametern inte specificeras alls, kommer komponenten automatiskt att läggas till i mitten c. add(new JButton(" Center")); // visa fönstret till skärmen set.Visible(true); ) public statc void main(String args) ( new Border.Layout.Sample(); ) ) Swing

Sekventiell placering (Flow. Layout layout) Layouten layoutar komponenter från vänster till höger, uppifrån och ned (standard i Jpanels). importera javax. gunga. *; importera java. awt. *; offentlig klass Flow. Layout. Sample utökar JFrame ( public Flow. Layout. Sample() ( super("Flow. Layout 1"); set. Size(400, 200); set. Default. Close. Operaton(EXIT_ON_CLOSE); // hämta innehållspanelen Container c = get.Content.Pane(); // ställ in komponenterna så att de centreras sekventiellt c.set.Layout(new Flow.Layout(Flow.Layout.CENTER)); // lägg till komponenterna c.add(new JButton( " One")); c. add(new JButton("Två")); c. add(new JButton("Tre")); // visa fönsteruppsättningen. Visible(true); ) public statc void main( String args) (ny Flow.Layout.Sample(); ) ) importera java. awt. *; importera javax. gunga. *; public class Soluton ( public static void main(String args) ( JOpton. Pane. show. Message. Dialog(null , "Hello, World"); ) ) Swing

Tabelllayout (Grid. Layoutlayout) alla komponenter har samma storlek. Det tillgängliga utrymmet är uppdelat i samma antal celler, i var och en av vilka komponenten är placerad; alla komponenter dras alltid till skärmen, oavsett hur stort eller litet det tillgängliga utrymmet är. importera java. awt. *; importera javax. gunga. *; importera java. utl. *; klass Grid. Test utökar JFrame ( Grid. Test(String s)( super(s); Container c = get. Content. Pane(); // 4 rader 4 kolumner avstånd mellan rader och kolumner i pixlar c. set. Layout(new Grid. Layout(4, 4, 5, 5)); String. Tokenizer st = ny String. Tokenizer("7 8 9 / 4 5 6 * 1 2 3 - 0. = +"); while(st. har. Mer. Tokens()) c. add(new Button(st. next. Token())); set. Size(200, 200); set. Visible(true); ) public statc void main(String args)( new Grid. Test(" Grid Manager. Layout"); ) ) Swing

En tabelllayout kommer att ge knapparna samma storlek, och en sekventiell layout kommer att förhindra att de "suddar ut" och samtidigt anpassa dem till högerkanten jag importerar java. awt. *; importera javax. gunga. *; allmän klass Kommando. Buttons utökar JFrame ( public Command. Buttons() ( super("Command. Buttons"); set. Size(350, 250); set. Locaton(150, 100); set. Default. Close. Operaton(EXIT_ON_CLOSE); / / skapa en panel med en tabelllayout för att justera knappstorlekar JPanel grid = new JPanel(new Grid. Layout(1, 2, 5, 0)); // 1 rad, 2 kolumner, 5 pixlar horisontellt, 0 vertikalt. // lägg till komponenter grid. add(new JButton("OK")); grid. add(new JButton("Cancel")); // placera resultatet i en högerjusterad sekventiell panel JPanel flow = new JPanel( new Flow.Layout (Flöde. Layout. HÖGER)); flow. add(grid); // hämta innehållsrutan Container c = get. Content. Pane(); // placera raden med knappar längst ner i fönstret c. add( flow, Border .Layout.SOUTH); // Display window set.Visible(true); ) public statc void main(String args) ( new Command.Buttons(); ) ) Swing

Boxlayout (Box. Layout layout) Boxlayouthanteraren lägger ut komponenter i en container i block: en kolumn (längs Y-axeln) eller en remsa (längs X-axeln), medan varje enskild komponent kan riktas in i mitten, vänster eller höger, såväl som på toppen eller botten.

Exempel på blockplacering import java. awt. *; importera javax. gunga. *; public class Box 1 utökar JFrame ( public Box 1() ( super("Box 1 - Y"); set. Size(400, 200); set. Standard. Close. Operaton(EXIT_ON_CLOSE); // hämta innehållspanelen Container c = get.Content.Pane(); // set y-box layout Box.Layout boxy = new Box.Layout(c, Box.Layout.Y_AXIS); c.set.Layout(boxy); // lägg till komponenter c . add(new JButton("One")); c. add(new JButton("Två")); c. add(new JButton("Tre")); // visa fönsteruppsättningen. Synlig (true); ) statc class Box 2 utökar JFrame ( public Box 2() ( super("Box 2 - X"); // ställ in boxens storlek och position. Size(400, 200); set. Locaton(100, 100) ); set.Default.Close.Operaton(EXIT_ON_CLOSE); // hämta innehållspanelen Container c = get.Content.Pane(); //set box x position (bar) Box.Layout boxx = new Box.Layout (c , Box. Layout. X_AXIS); c. set. Layout(boxx); // lägg till komponenter c. add(new JButton("One")); c. add(new JButton("Två")); c .add (ny JButton("Tre")); // visa fönstret på skärmen. synlig (sant); ) ) public statc void main(String args) (new Box 1(); new Box 2(); ) ) Swing 5 Detta exempel skapar två fönster. En av dem implementerar blocklayout längs Y-axeln, den andra - blocklayout längs X-axeln.

Davydov Anton Valerievich
Student vid TSU, Ryssland, Togliatti
Vetenskaplig rådgivare: Erofeeva E.A.

Användargränssnittet i Java har gått igenom en mycket besvärlig väg av bildning och utveckling. Det har länge anklagats för att vara girigt på systemresurser, långsam prestanda och begränsad funktionalitet. Tillkomsten av .NET med snabbare grafiska komponenter har ytterligare skakat Javas position. Men sådan konkurrens stimulerade bara Java-utvecklare till utveckling och förbättring av grafiska bibliotek. Och i den här artikeln kommer vi att se vad som blev av det.

Abstrakt fönster verktygslåda

The Abstract Window Toolkit (AWT förkortat) släpptes först 1995 av Sun Microsystems. Det var det första försöket att skapa ett GUI för Java. AWT fungerade som ett lager som anropade metoder från bibliotek skrivna i C. Och dessa metoder använde i sin tur de grafiska komponenterna i operativsystemet. Dels såg ett program som byggts upp på detta sätt likt ut alla andra program på operativsystemet som används, men å andra sidan kan samma program se helt olika ut på olika operativsystem, vilket försvårar utvecklingen. Dessutom, för multiplattformens skull, var det nödvändigt att förena komponenternas samtalsgränssnitt, vilket ledde till något trunkerad funktionalitet. Uppsättningen av komponenter är också ganska blygsam. Det finns till exempel inga tabeller och ikoner kan inte placeras i knappar. AWT försöker automatiskt släppa använda resurser. Detta påverkar prestandan och komplicerar arkitekturen. AWT är lätt att lära sig, men att skriva något komplext är svårt. Nu används AWT främst för applets. Oracle uppmuntrar för närvarande utvecklare att byta till Swing eftersom det är säkrare.

Fig.1 - Ett exempelprogram skrivet med AWT i en Windows-miljö

Efter AWT, 1998, släppte Sun Swing. Den är helt skriven i Java och använder 2D för rendering. Swing har mycket mer olika komponenter än AWT. Komponenterna i sig har blivit mycket lättare att skapa genom att ärva från befintliga. Möjligheten att använda olika stilar och skinn introducerades också. Men hastigheten på tidiga versioner av Swing var ganska långsam, och fel i att skriva ett program kan till och med leda till att operativsystemet fryser.

Men på grund av dess enkla inlärning och tillgången på en stor mängd dokumentation, har Swing blivit det mest populära GUI i Java. Baserat på det har många tillägg dykt upp, som SwingX och JGoodies, som gör det ännu enklare att skapa visuellt komplexa applikationer. Alla moderna Java-programmeringsmiljöer inkluderar grafisk redaktör Gunga. Även om det finns mer moderna ramverk nu, är Swing fortfarande det mest populära.


Fig. 2 - Exempelprogram skrivet med Swing

Standard Widget Toolkit

SWT släpptes av IBM vid en tidpunkt då Swing fortfarande var långsam, och främst för att främja Eclipse-programmeringsmiljön. Liksom AWT använder SWT OS-komponenter, men olika interoperabilitetsgränssnitt används för olika plattformar. Därför måste ett separat JAR-bibliotek levereras för varje operativsystem. Detta gör att du kan använda funktionerna som motsvarar olika operativsystem mer fullständigt. Och de saknade komponenterna implementerades med 2D. SWT visade sig dock vara svårare att bemästra än Swing. Dessutom måste programmeraren själv implementera frisläppandet av resurser av applikationen.

Fig.3 - Exempelprogram skrivet med Swing

JavaFX släpptes 2008 av Oracle. Den är placerad som en plattform för att skapa en rik internetapplikation. För rendering används en grafisk pipeline, vilket avsevärt snabbar upp applikationen. Det finns en stor uppsättning inbyggda komponenter. Det finns också separata komponenter för att rita grafer. Implementerat stöd för multimediainnehåll, animering och till och med multi-touch. Komponenternas utseende konfigureras med CSS-stilar. Dessutom inkluderar uppsättningen av JavaFX-verktyg möjligheten att skapa ett inbyggt installationsprogram för de mest populära plattformarna: exe eller msi för Windows, deb eller rpm för Linux, dmg för Mac. Oracles webbplats har detaljerad dokumentation och ett stort antal färdiga exempel.

Efter att ha beskrivit huvudfunktionerna och nackdelarna med ovanstående grafiska användargränssnitt kan vi bestämma vilka uppgifter de är bäst lämpade för. Verktygslådan för abstrakta fönster är mer lämplig för att skapa appletar. En nybörjare kan rekommendera Swing med tanke på det faktum att du kan hitta en enorm mängd dokumentation för det på Internet, inklusive på ryska. JavaFX är bra för att bygga rika internetapplikationer.

Lista över använda källor

    Ryzhenko A.V. Objektorienterad programmering: Utbildnings- och metodkomplex för disciplinen för specialiteten 010501 - "Tillämpad matematik och informatik". – 2007.

    Khabibullin I. Sh. Java 7 (4:e upplagan). - BHV-Petersburg, 2012.

    Clarke J., Connors J., Bruno E. J. JavaFX: Utveckla rika internetapplikationer. – Pearson Education, 2009.

    Northover S., Wilson M. Swt: standardwidgetverktygssatsen, volym 1. - Addison Wesley Professional, 2004.

Användargränssnittet i Java har gått igenom en mycket besvärlig väg av bildning och utveckling. Under en lång tid han anklagades för långsamt arbete, girighet efter systemresurser, begränsad funktionalitet. Tillkomsten av .NET med snabbare grafiska komponenter har ytterligare skakat Javas position. Men varje moln har en silverkant - all denna rörelse sporrade bara Java-utvecklare att utveckla och förbättra grafikbibliotek. Låt oss se vad som blev av det.

Abstrakt fönster verktygslåda

AWT var Suns första försök med ett GUI för Java. De gick den enkla vägen och gjorde bara ett Java-lager som anropar metoder från bibliotek skrivna i C. Biblioteksmetoderna skapar och använder de grafiska komponenterna i operativmiljön. Å ena sidan är detta bra, eftersom ett Java-program liknar andra program inom detta operativsystem. Men å andra sidan finns det ingen garanti för att skillnader i komponentstorlekar och teckensnitt inte kommer att förstöra programmets utseende när det körs på en annan plattform. Dessutom, för att säkerställa multiplattform, var det nödvändigt att förena komponenternas samtalsgränssnitt, varför deras funktionalitet visade sig vara lite trunkerad. Och uppsättningen av komponenter visade sig vara ganska liten. Till exempel har AWT inga tabeller och knappar stöder inte visning av ikoner.

Använda resurser AWT försöker släppa automatiskt. Detta komplicerar arkitekturen något och påverkar prestandan. Att lära sig AWT är ganska enkelt, men att skriva något komplext kan vara lite knepigt. Nu används den bara för applets.

Fördelar:

  • del av JDK;
  • arbetshastighet;
  • grafiska komponenter liknar standardkomponenterna.

Brister:

  • användningen av inhemska komponenter medför restriktioner för användningen av deras egenskaper. Vissa komponenter kanske inte fungerar alls på "icke-native" plattformar;
  • vissa egenskaper, som ikoner och verktygstips, finns inte alls i AWT;
  • Det finns väldigt få standardkomponenter för AWT, programmeraren måste implementera många anpassade;
  • programmet ser annorlunda ut olika plattformar(kan vara sned).

slutsats:

För närvarande används AWT extremt sällan - främst i gamla projekt och applets. Oracle gömde handledningarna och uppmuntrar starkt övergången till Swing. Detta är förståeligt, direkt tillgång till komponenterna i axeln kan vara ett allvarligt säkerhetshål.

Gunga


Efter AWT utvecklade Sun en uppsättning grafiska komponenter som heter Swing. Swing-komponenter är helt skrivna i Java. 2D används för rendering, vilket ger flera fördelar samtidigt. Uppsättningen av standardkomponenter överträffar vida AWT när det gäller variation och funktionalitet. Det har blivit lätt att skapa nya komponenter, ärva från befintliga och rita vad du än vill. Stöd för olika stilar och skal har blivit möjligt. Men hastigheten på de första versionerna av Swing lämnade mycket att önska. Ett felaktigt skrivet program kan till och med hänga Windows hårt.

Ändå, på grund av sin användarvänlighet, rika dokumentation och flexibla komponenter, har Swing blivit det kanske mest populära grafikramverket i Java. Många tillägg har dykt upp på grundval av det, som SwingX, JGoodies, som avsevärt förenklar skapandet av komplexa användargränssnitt. Nästan alla populära Java-programmeringsmiljöer inkluderar grafiska redigerare för Swing-formulär. Därför blir det inte svårt att förstå och börja använda Swing.

Fördelar:

  • del av JDK, inget behov av att installera ytterligare bibliotek;
  • det finns många fler böcker och forumsvar på Swing. Alla problem, särskilt för nybörjare, är välkända för Google;
  • inbyggd formredigerare i nästan alla utvecklingsmiljöer;
  • det finns många tillägg baserade på swing som SwingX;
  • stöd för olika stilar (utseende och känsla).

Brister:

  • ett fönster med många komponenter börjar sakta ner;
  • att arbeta med layouthanterare kan vara en riktig mardröm i komplexa gränssnitt.

Slutsats:

Swing har levt, Swing lever, Swing kommer att leva. Även om Oracle försöker marknadsföra JavaFX, är Swing fortfarande det mest populära Java UI-ramverket idag.

Standard Widget Toolkit


Hur
utseende
SWT

SWT utvecklades på IBM på den tiden då Swing fortfarande var långsam, och det gjordes främst för att främja Eclipse-programmeringsmiljön. SWT, liksom AWT, använder operativsystemkomponenter, men det har sina egna interaktionsgränssnitt för varje plattform. Så för var och en nytt system du måste skicka ett separat JAR-bibliotek med lämplig SWT-version. Detta möjliggjorde mer fullständig användning av de befintliga funktionerna hos komponenterna på varje axel. De saknade funktionerna och komponenterna implementerades med 2D, som i Swing. SWT har många anhängare, men i ärlighetens namn kan man inte annat än hålla med om att allt visade sig inte vara så enkelt som vi skulle önska. En nybörjare kommer att behöva lägga mycket mer tid på att lära sig SWT än att bekanta sig med samma Swing. Dessutom lägger SWT uppgiften att släppa resurser på programmeraren, och därför måste han vara särskilt försiktig när han skriver kod så att ett oavsiktligt undantag inte leder till minnesläckor.

Fördelar:

  • använder operativsystemkomponenter - hastigheten är högre;
  • Eclipse ger visuell redaktör former;
  • omfattande dokumentation och många exempel;
  • det är möjligt att använda AWT och Swing komponenter.

Brister:

  • för varje plattform är det nödvändigt att tillhandahålla ett separat bibliotek;
  • du måste ständigt övervaka användningen av resurser och frigöra dem i tid;
  • komplex arkitektur som väcker självmordstankar efter meningslösa försök att implementera ett anpassat gränssnitt.

Slutsats:

Det kan ses att IBM försökte. Men det blev väldigt amatörmässigt...

JavaFX


JavaFX kan kallas ett genombrott utan att överdriva. För rendering används en grafisk pipeline, vilket avsevärt snabbar upp applikationen. Uppsättningen av inbyggda komponenter är omfattande, det finns till och med separata komponenter för att rita grafer. Implementerat stöd för multimediainnehåll, många visningseffekter, animationer och till och med multi-touch. Utseendet på alla komponenter kan enkelt ändras med CSS-stilar. Och det bästa är att JavaFX innehåller en uppsättning verktyg som låter dig skapa ett inbyggt installationsprogram för de mest populära plattformarna: exe eller msi för Windows, deb eller rpm för Linux, dmg för Mac. På Oracles webbplats kan du hitta detaljerad dokumentation och ett stort antal färdiga exempel. Detta gör programmering med JavaFX enkelt och roligt.

Fördelar:

  • snabbt arbete på grund av grafikpipelinen;
  • många olika komponenter;
  • stilstöd;
  • verktyg för att skapa ett programinstallationsprogram;
  • applikationen kan startas som ett skrivbord och i webbläsaren som en del av sidan.

Brister:

  • ramverket håller fortfarande på att utvecklas, så krascher och vissa fel inträffar;
  • JavaFX används ännu inte i stor utsträckning.

Slutsats:

Bra jobbat, Oracle. Ramen lämnar bara positiva intryck. Det är lätt att förstå, metoder och gränssnitt ser logiska ut. Jag vill använda igen och igen!

Visuella bibliotek i praktiken

SWT: väderwidget

För att demonstrera kapaciteten hos de mest populära grafiska biblioteken och de grundläggande principerna för att arbeta med dem kommer vi att göra flera små widgets som visar olika information.

Och låt oss börja, kanske, med den mest populära widgeten - visa det aktuella vädret, för genomförandet av vilket vi kommer att välja SWT.

Alla SWT-program börjar med skapandet av ett Display-objekt. Det fungerar som ett slags applikationskontext som innehåller de nödvändiga metoderna för att komma åt systemresurser och tillhandahåller en händelseloop. Nästa steg är att skapa det lika viktiga Shell-objektet. Shell är ett normalt operativsystemfönster. Displayen skickas till skalkonstruktören för att skapa ett fönster på toppnivå.

Display display = new Display(); skal = nytt skal(display, SWT.NO_TRIM);

Eftersom vi skapar en widget behöver vi inte visa standardfönsterramen och kontrollknapparna, för detta har vi specificerat NO_TRIM-flaggan. För bakgrunden kommer vi att använda en bild - en rektangel med rundade hörn. I princip kan ett SWT-fönster anta vilken form som helst. För att uppnå denna effekt använder vi klassen Region. Allt som behövs är att lägga till alla synliga punkter från bakgrundsbilden till denna klass och hoppa över de genomskinliga.

Ladda upp en bild:

Bildbild = ny bild(display, "images/bg.png#26759185");

I bilder av olika format ställs transparens in på olika sätt, så information om transparenta områden hämtas inte heller på samma sätt. Skapa ett bakgrundsområde och lägg till alla synliga prickar där:

Region region = new Region(); ImageData imageData = image.getImageData(); if (imageData.alphaData != null) ( rektangelpixel = ny rektangel(0, 0, 1, 1); för (int y = 0; y< imageData.height; y++) { for (int x = 0; x < imageData.width; x++) { if (imageData.getAlpha(x, y) == 255) { pixel.x = imageData.x + x; pixel.y = imageData.y + y; region.add(pixel); } } } } else { ImageData mask = imageData.getTransparencyMask(); Rectangle pixel = new Rectangle(0, 0, 1, 1); for (int y = 0; y < mask.height; y++) { for (int x = 0; x < mask.width; x++) { if (mask.getPixel(x, y) != 0) { pixel.x = imageData.x + x; pixel.y = imageData.y + y; region.add(pixel); } } } }

Ställ in fönsterformen:

Shell.setRegion(region);

Nu måste vi skapa en händelseavlyssnare för fönstret. Vi kommer att vara intresserade av fönsterritningshändelser, mushändelser och tangenttryckningar så att fönstret kan flyttas runt på skärmen.

Listener listener = new Listener() ( int startX, startY; public void handleEvent(Event e) ( if (e.type == SWT.KeyDown && e.character == SWT.ESC) ( shell.dispose(); ) if (e.type == SWT.MouseDown && e.button == 1) ( startX = e.x; startY = e.y; ) if (e.type == SWT.MouseMove && (e.stateMask & SWT.BUTTON1) != 0 ) ( Punkt p = shell.toDisplay(e.x, e.y); p.x -= startX; p.y -= startY; shell.setLocation(p); ) if (e.type == SWT.Paint) ( e.gc.drawImage( image, imageData.x, imageData.y); ) ) );

Så genom att trycka på Esc-tangenten stängs fönstret. När du trycker på vänster musknapp på området i fönstret, kom ihåg koordinaterna för klicket. När vi flyttar musen med vänster knapp nedtryckt flyttar vi fönstret på skärmen efter rörelsen. Vid omritningshändelse - rita bakgrundsbild med GC-grafikkontext.

Tilldela en lyssnare till motsvarande fönsterhändelser:

Shell.addListener(SWT.KeyDown, lyssnare); shell.addListener(SWT.MouseDown, lyssnare); shell.addListener(SWT.MouseMove, lyssnare); shell.addListener(SWT.Paint, lyssnare);

Ställ in fönsterstorleken till bildens storlek:

Shell.setSize(imageData.x + imageData.width, imageData.y + imageData.height);

Öppna fönstret och kör händelseslingan:

Shell.open(); while (!shell.isDisposed ()) ( if (!display.readAndDispatch ()) display.sleep (); )

Glöm inte att släppa de använda resurserna i slutet:

region.dispose(); image.dispose(); display.dispose();

Genom att köra programmet i detta skede får vi en rektangel som kan flyttas med musen och stängas med Esc.

Det är dags att lägga till innehåll. Vi kommer att visa det aktuella vädret i form av en statusikon (sol, regn, snö ...), temperaturavläsningar och tidpunkten för den senaste uppdateringen.

Layouthanterare används för att ordna grafiska komponenter i fönstret i önskad form. Layouthanteraren är bekymrad inte bara med arrangemanget av komponenter, utan också med deras storleksändring när fönstret ändras. Vi kommer att använda GridLayout för vår widget. Denna manager ordnar komponenterna i cellerna i en imaginär tabell. Skapa en GridBagLayout för två kolumner med olika kolumnbredder (falsk flagga i konstruktorn), ställ in den som fönsterlayouthanterare:

GridLayout layout = new GridLayout(2, false); shell.setLayout(layout);

För statusbilden använder vi Label-komponenten. Vi skickar fönsterobjektet som förälder. Den andra parametern är att ställa in stilen för komponenten. För varje komponent är uppsättningen av möjliga stilflaggor olika, de kan hittas i dokumentationen eller direkt i källkoden för komponenten.

//draw status image Label imageLabel = new Label(shell, SWT.NONE); imageLabel.setLayoutData(new GridData(SWT.LEFT, SWT.TOP, true, true, 1, 1));

Flaggorna i GridData-klassen betyder att etiketten kommer att placeras överst till vänster, sträcker sig horisontellt och vertikalt (flaggor satta till true) när det finns ledigt utrymme, och upptar en rad och en kolumn i layouttabellen.

Inte i SWT genomskinlig bakgrund komponenter, och en vit bakgrund kommer att synas bakom statusbilden, vilket naturligtvis inte skulle vara önskvärt. Så låt oss skapa ett färgobjekt med fönstrets bakgrundsfärg:

Färg bgColor = ny färg(display, 0x2b, 0x2b, 0x2b);

I slutet av programmet måste även detta objekt rensas upp genom att anropa dispose-metoden. Ställ in bakgrundsfärg och statusbild, som kan laddas från en fil på samma sätt som vi laddade bakgrundsbilden i början:

ImageLabel.setBackground(bgColor); Image statusImage = new Image(display, "images/1.png#26759185"); imageLabel.setImage(statusImage);

Låt oss nu lägga till en etikett med den aktuella temperaturen och placera den i den övre högra delen av fönstret:

Label temperatureLabel = new Label(shell, SWT.NONE); temperatureLabel.setLayoutData(new GridData(SWT.RIGHT, SWT.TOP, false, false, 1, 1));

Låt oss ställa in lite temperatur:

TemperatureLabel.setText("+1 \u2103");

För att registrera temperaturen i Celsius används Unicode-numret för motsvarande tecken med servicetecknen \u.

Standardteckensnittet för textetiketter är för litet. Så låt oss skapa en ny, större:

FontData fD = temperatureLabel.getFont().getFontData(); fD.setHeight(30); fD.setStyle(SWT.BOLD); Font newFont = new Font(display, fD); temperatureLabel.setFont(newFont); Typsnittet måste, liksom andra resursobjekt, frigöras. För att göra detta använder vi etikettdestruktionshändelselyssnaren:

TemperatureLabel.addDisposeListener(new DisposeListener() ( public void widgetDisposed(DisposeEvent e) ( newFont.dispose(); ) ));

Låt oss slutligen lägga till en etikett som beskriver väderförhållandena:

EtikettbeskrivningLabel = new Label(shell, SWT.WRAP); descriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, true, 2, 1)); descriptionLabel.setText("Molnigt med gläntor, lätt regn"); descriptionLabel.setBackground(bgColor); descriptionLabel.setForeground(display.getSystemColor(SWT.COLOR_WHITE));

Texten kan vara ganska lång, så när vi skapar etiketten anger vi WRAP-flaggan så att texten automatiskt delas upp i flera rader när det inte finns tillräckligt med utrymme. Låt oss centrera komponenten och låta den fylla hela det horisontella utrymmet. Vi anger också att komponenten upptar två kolumner i layouttabellen. Vi startar och får ett fönster från bilden "Weather Widget".

Nu kan du koppla upp någon slags vädertjänst, skapa en timer för automatiska uppdateringar – och widgeten är klar.

Swing: alltid färska nyheter

I Swing kommer vi att skriva en widget för att visa RSS-flöden. Vi börjar, som förra gången, med att skapa ett fönster. Klassen som implementerar standardfönsterfunktionaliteten i Swing kallas JFrame. Som standard kommer inte programmet att stoppas om ett programfönster stängs i Swing, så det är bättre att ange hur fönstret ska bete sig när det stängs:

JFrame frame = new JFrame(); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);

Ett bord är bäst för att presentera nyheter. Swing är byggd på mönstret Model-View-Controller (MVC). I MVC-arkitekturen tillhandahåller modellen data, vyn ansvarar för att visa data (t.ex. text, inmatningsfält) och styrenheten tillhandahåller interaktionen mellan modellen och vyn. Tabellen visar detta tillvägagångssätt väl. För att representera data används en klass som implementerar TableModel-gränssnittet.

För att lagra information om tillgängliga nyheter, låt oss skapa en FeedMessage-klass med fält för artikelns titel och releasedatum:

Offentlig klass FeedMessage ( offentlig strängtitel; offentligt datum publiceringsdatum; )

För att förenkla och påskynda utvecklingen ärver vi vår datamodell från klassen AbstractTableModel, som erbjuder en färdig implementering av nästan alla metoder i TableModel-gränssnittet.

Public class RssFeedTableModel utökar AbstractTableModel (privat lista poster = ny ArrayList<>(); public void updateData(List entries) ( this.entries = entries; fireTableDataChanged(); ) public int getRowCount() ( return entries.size(); ) public int getColumnCount() ( return 2; ) public Object getValueAt(int rowIndex, int columnIndex) ( switch (columnIndex) ( fall 0: return entries.get(rowIndex).title; fall 1: return entries.get(rowIndex).publicationDate; ) return null; ) )

FireTableDataChanged-metoden talar om för vyn att datamodellen har ändrats och måste återges.

Vi skapar en tabell och ändrar dess utseende lite så att den ser mer ut som en widget. Vi tar bort raderna mellan rader och kolumner, ökar radhöjden och tar bort tabellrubriken med kolumnnamn:

JTable table = new JTable(new RssFeedTableModel()); tablesetShowGrid(false); table.setIntercellSpacing(ny dimension(0, 0)); tablesetRowHeight(30); table.setTableHeader(null);

Låt oss nu bli upptagna utseende celler. Swing låter dig tilldela separata vyklasser till olika datatyper. Klassen som ärver TableCellRenderer-gränssnittet är ansvarig för att rendera individuella tabellceller. Standard är DefaultTableCellRenderer som är en textetikett.

Låt oss tilldela vår cellrenderare till strängdata. Låt oss ändra standardtypsnittsfärgen och göra bakgrundsfärgen alternativ för att förbättra läsbarheten.

Table.setDefaultRenderer(String.class, new DefaultTableCellRenderer() ( Color oddColor = new Color(0x25, 0x25, 0x25); Color evenColor = new Color(0x1a, 0x1a, 0x1a); Color titleColor = new Color(0xa2, 0xa2, 0xa2, 0xa2, 0xa2a, 0xa2a, 0xa7 ); public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) (super.getTableCellRendererComponent(tabell, värde, isSelected, hasFocus, rad, kolumn); setBackground(rad % 2 == 0 ?oddColor: evenColor); setForeground(titleColor); setFont(font); returnera detta; ) ));

För att tabellen ska börja använda vår renderare måste vi lägga till en metod som returnerar datatypen för varje cell till datamodellen:

offentlig klassgetColumnClass(int columnIndex) ( switch (columnIndex) ( fall 0: return String.class; fall 1: return Date.class; ) return Object.class; )

Det kan finnas många nyheter, så låt oss lägga tabellen på rullningslisten och göra rullningslisten osynlig så att den inte förstör vår widgetdesign:

JScrollPane scrollPane = ny JScrollPane(tabell); table.setFillsViewportHeight(true); scrollPane.getVerticalScrollBar().setPreferredSize(ny dimension(0,0));

Lägga till en rullningskomponent till huvudfönstret i fönstret. Det andra argumentet kan vara platsen för komponenten. Som standard använder huvudfönstret i ett fönster BorderLayout-layouthanteraren, som lägger ut komponenter efter kardinalriktningar. Låt oss placera bordet med rullning i mitten.

Frame.getContentPane().add(scrollPane, BorderLayout.CENTER);

Som förra gången tar vi bort standardfönsterkarmen. Och som titel på fönstret kommer vi att använda en stiliserad textetikett, som vi placerar överst i fönstret.

JLabel titleLabel = new JLabel("Xakep RSS"); Font titleFont = new Font("Arial", Font.BOLD, 20); titleLabel.setFont(titleFont); titleLabel.setHorizontalAlignment(SwingConstants.CENTER); titleLabel.setForeground(Color.WHITE); titleLabel.setPreferredSize(ny dimension(0, 40)); frame.getContentPane().add(titleLabel, BorderLayout.NORTH);

Till skillnad från SWT avallokeras objekten "färg" och "font" automatiskt, så du behöver inte oroa dig för minnesläckor längre.

Vi lägger till muslyssnare så att fönstret kan flyttas runt på skärmen.

MouseAdapter-lyssnare = ny MouseAdapter() ( int startX; int startY; public void mousePressed(MouseEvent e) ( if (e.getButton() == MouseEvent.BUTTON1) ( startX = e.getX(); startY = e.getY( ); ) ) public void mouseDragged(MouseEvent e) ( Point currCoords = e.getLocationOnScreen(); frame.setLocation(currCoords.x - startX, currCoords.y - startY); ) ); titleLabel.addMouseListener(lyssnare); titleLabel.addMouseMotionListener(lyssnare);

Ändra nu fönstrets form till en rektangel med rundade hörn. Det är bäst att göra detta i komponentens lyssnare, för om fönsterstorleken ändras kommer fönstrets form att räknas om korrekt:

Frame.addComponentListener(new ComponentAdapter() ( public void componentResized(ComponentEvent e) ( frame.setShape(new RoundRectangle2D.Double(0, 0, frame.getWidth(), frame.getHeight(), 20, 20)); ) ) );

Ställ in storleken på fönstret, ta bort ramen och gör fönstret halvtransparent.

Frame.setSize(520, 300); frame.setUdecorated(true); frame.setOpacity(0.85f);

Slutligen öppnar vi ett fönster i grafiktråden. SwingUtilities.invokeLater(new Runnable() ( public void run() ( frame.setVisible(true); ) ));

Det återstår att lägga till dataladdning i en separat tråd, och vi kommer att få en sådan widget med de senaste nyheterna från din favorittidning :).


JavaFX: Låt oss lyssna på musiken

Och slutligen, säsongens höjdpunkt är JavaFX. Låt oss använda dess multimediafunktioner och grafiska komponent och göra en enkel equalizer.

Först ärver vi widgetklassen från Application. Detta är huvudapplikationsklassen i JavaFX. Ansökan innehåller de viktigaste metoderna för applikationens livscykel. Formulärkomponenter skapas i startmetoden, vars argument är Stage-klassen. Stage representerar programmets fönster. Ändra fönsterstilen till TRANSPARENT för att ta bort ram och knappar. Klassen Stage innehåller klassen Scene, som anger storleken på fönstret och bakgrundsfärgen. I Scene passerar vi i sin tur gruppklassen, där vi kommer att placera barnkomponenter:

Public void start(Stage primaryStage) ( primaryStage.initStyle(StageStyle.TRANSPARENT); Group root = new Group(); Scen scen = new Scene(root, 400, 200, Color.TRANSPARENT); primaryStage.setScene(scen);

För att visa equalizern använder vi ett stapeldiagram, längs vars axlar vi kommer att visa frekvensen och ljudstyrkan:

CategoryAxis xAxis = new CategoryAxis(); NumberAxis yAxis = new NumberAxis(0,50,10); BarChart bc = nytt stapeldiagram (xAxis,yAxis); bc.setPrefSize(400, 200); bc.setLegendVisible(false); bc.setAnimated(false); bc.setBarGap(0); bc.setCategoryGap(1); bc.setVerticalGridLinesVisible(false); bc.setHorizontalGridLinesVisible(false); xAxis.setLabel("Frekvens"); yAxis.setLabel("Power"); yAxis.setTickLabelFormatter(ny NumberAxis.DefaultFormatter(yAxis, null, "dB"));

Fyll i diagrammet med initiala data:

XYChart.Series serie1 = ny XYChart.Series (); series1Data = ny XYChart.Data; Strängkategorier = ny sträng; för (int i=0; i (kategorier[i], 50); series1.getData().add(series1Data[i]); ) bc.getData().add(serie1);

Skapa en rektangel med rundade hörn för att ge widgeten rätt form:

Rektangel rektangel = ny Rektangel(0, 0, 400, 200); Stop stops = new Stop ( new Stop(0, new Color(0, 0, 0, 0.8)), null); LinearGradient lg2 = new LinearGradient(0, 0, 0, 0, false, CycleMethod.NO_CYCLE, stopp); rectangle.setFill(lg2); rectangle.setArcHeight(20); rectangle.setArcWidth(20);

Lägg till båda komponenterna i gruppen:

Root.getChildren().addAll(rektangel, bc);

Tilldela muslyssnare till gruppen för att flytta fönstret runt skärmen:

Root.setOnMousePressed(ny EventHandler () ( public void handle(MouseEvent me) ( initX = me.getScreenX() - primaryStage.getX(); initY = me.getScreenY() - primaryStage.getY(); ) )); root.setOnMouseDragged(ny EventHandler () ( public void handle (MouseEvent me) ( primaryStage.setX(me.getScreenX() - initX); primaryStage.setY(me.getScreenY() - initY); ) ));

Ladda ner låten till spelaren:

File file = new File("släpp mig härifrån.mp3"); media audioMedia = null; audioMedia = new Media(file.toURI().toURL().toString()); audioMediaPlayer = ny MediaPlayer(audioMedia);

Lägg till en lyssnare som uppdaterar stapeldiagrammet:

AudioMediaPlayer.setAudioSpectrumListener(new AudioSpectrumListener() ( public void spectrumDataUpdate(dubbel tidsstämpel, dubbel varaktighet, flytstorlekar, flytfaser) ( för (int i = 0; i< series1Data.length; i++) { series1Data[i].setYValue(magnitudes[i] + 60); } } });

Gör scenen synlig och spela låten:

PrimaryStage.show(); audioMediaPlayer.play();

Vi startar applikationen:

Public static void main(String args) ( launch(args); )

Och njut av denna skönhet.