Minimize a resizable JDialog - swing

I'm working on an swing application with a main window (which extends JFrame) from which several child windows can be opened (more than 1 contemporarily).
These windows are all non-modal and resizable.
So far, I implemented these 'child' windows as a JFrame. However, I get a new icon on my Windows taskbar for each opened Window.
I therefore tried to implement these windows as a JDialog with type ModalityType.MODELESS.
Looks OK except that a JDialog has no minimize button.
Is there a way to resolve this?
I.e., I need to create non-modal and resizable child windows that can be minimized.
JInternalFrame is not an option since the main frame is not just a container with a JDesktopPane and child windows should be able to cross the borders of the main window.
For those interested:
Child windows register and unregister themselves on the main window when being opened/closed.
The main window has a menu with a 'Windows' item and child windows are added/removed from that menu upon registration/unregistration.
The user can switch between the various windows by selecting an item within this menu.

I am offering two suggestions.
A. Don't use the close button to get rid of the contents.
B. Set the type of child jframes to be utility.
I think having the JDialog close button destroy data is setting your users up for data loss. I would instead use the close to just hide the window, and then have controls inside of the dialog to cancel/finish/restart.
import java.awt.*;
public class DiFrame{
static JDialog log;
static JFrame ame;
public static void main(String[] args){
JFrame frame = new JFrame("Father of two");
JButton one = new JButton("dialog");
one.addActionListener( evt->{
if(log==null){
log = new JDialog(frame, "dialog child", false);
log.add(new JTextArea("fresh start"));
log.pack();
log.setVisible(true);
} else{
log.setVisible(true);
}
});
JButton two = new JButton("frame");
two.addActionListener( evt->{
if(ame==null){
ame = new JFrame("frame child");
ame.add( new JTextArea("fresh start") );
ame.setType(Window.Type.UTILITY);
ame.pack();
ame.setVisible(true);
} else{
ame.setVisible(true);
}
});
frame.add(one, BorderLayout.NORTH);
frame.add(two, BorderLayout.SOUTH);
frame.pack();
frame.setVisible(true);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
}
Click the dialog button and it shows the dialog. Then the text area can be modified. When the dialog is closed it can be re-opened.
Click the frame button and a jframe is shown. ( I actually cannot check if this shows up as a new application because it doesn't on my computer anyways. )

Related

Libgdx stage 'frozen"

In my game there is a menu, in this menu, there are 4 tabs and each tab have its own stage with tables scrollpanes and buttons (is it a good idea ?)
My problem is that every stage seems "frozen", buttons are not responding and scrollpanes don't scroll
My menu structure :
Menu class
-> render a tab (render selectedTab, selectedTab is a Tab object (custom class) that is asigned with a specific tab (Ex: sele shopTab (extend tab class))
// menu class
private Tab selectedTab;
private Tab RecipeTab, SellTab, UpgradeTab, ShopTab;
// menu constructor
RecipeTab = new RecipeTab(viewport, sb, itemsdata);
SellTab = new SellTab(viewport, sb, hud);
UpgradeTab = new UpgradeTab(viewport, sb, itemsdata);
ShopTab = new ShopTab(viewport, sb);
selectedTab = RecipeTab;
// render
selectedTab.render(sr, delta);
// on tab change
public void setSelectedTab(Tab newTab) {selectedTab = newTab;}
setSelectedTab(ShopTab);
-> menu contain a navbar to switch tabs (the selected tab is asigned with another tab object)
I don't know if the issue comes from the stages or the actors. even a simple textbutton doesn't work
// how my stages are made
// constructor
this.stage = new Stage(viewport, sb); // ExtendViewport (same everywhere), Spritebatch
Gdx.input.setInputProcessor(this.stage);
// render
this.stage.draw();
this.stage.act(delta);
I figured it out.
The answer was simple, there was a conflict with the inputProcessor
i was seting the inputProcessoron each tabs
so i added a setInputProcessor() method to the tabs a called it on tab change

InputPane does not work correctly

I'm currently developing an Universal Application, but here is a problem. I have a Frame with the TextBox for User Phone Number.
So, I want to change the height of my LayoutRoot (GRID) so it can fits in the free space.
I'm using InputPane.GetForCurrentView().Showing and InputPane.GetForCurrentView().Hiding for that purposes.
Here is my code.
public UserRegistrationAuthorization_PhoneNumber()
{
this.InitializeComponent();
LayoutRootInitialHeight = LayoutRoot.ActualHeight;
InputPane.GetForCurrentView().Showing += UserRegistrationAuthorization_PhoneNumber_Showing;
InputPane.GetForCurrentView().Hiding += UserRegistrationAuthorization_PhoneNumber_Hiding;
}
private void UserRegistrationAuthorization_PhoneNumber_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
{
LayoutRoot.Height = LayoutRoot.ActualHeight - args.OccludedRect.Height;
LayoutRoot.VerticalAlignment = VerticalAlignment.Top;
args.EnsuredFocusedElementInView = true;
}
private void UserRegistrationAuthorization_PhoneNumber_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)
{
// TODO: Get rid of that shit
LayoutRoot.Height = LayoutRootInitialHeight;
args.EnsuredFocusedElementInView = false;
}
When I click outside the TextBox keyboard hides and leaves after that a black hole on the screen. 2
But, the most interesting is that when I press that physical Back Button on my Lumia, keyboard hides normally and my LayoutRoot gets the Frame's initial height.
Is it a bug or I'm doing something wrong?
It happens because by the time you saving your LayoutRootInitialHeight in the constructor, LayoutRoot actually isn't loaded and it's ActualHeight == 0. Then you setting LayoutRoot.Height to 0, so it becomes not visible. So you should probably save your LayoutRootInitialHeight in LayoutRoot's Loaded event handler.
I would also suggest you not to change LayoutRoot's height at all. It causes your whole visual tree to be rendered from scratch and it's bad practise in general. Instead, modify RenderTransform of all necessary elements so they get moved to appropriate positions. RenderTransform is the right way to handle movements and animations on the screen, and you can achieve some nice visual effects with Next button moving up same as keyboard.
Roughly your code can look like this:
<Button Content="Next" VerticalAlignment="Bottom" HorizontalAlignment="Stretch" HorizontalContentAlignment="Center">
<Button.RenderTransform>
<CompositeTransform x:Name="NextButtonTransform" TranslateY="0"/>
</Button.RenderTransform>
</Button>
...
private void UserRegistrationAuthorization_PhoneNumber_Showing(InputPane sender, InputPaneVisibilityEventArgs args)
{
NextButtonTransform.TranslateY = -300;
EnsuredFocusedElementInView = true;
}
private void UserRegistrationAuthorization_PhoneNumber_Hiding(InputPane sender, InputPaneVisibilityEventArgs args)
{
NextButtonTransform.TranslateY = 0;
args.EnsuredFocusedElementInView = false;
}
And more complicated way is to run some storyboard which makes your Next button move up and down in same speed with keyboard, always appearing on top of it. Although, since InputPane.GetForCurrentView().Showing gets fired after keyboard already shown fully, you should hook up all animations to TextBox.GotFocus and TextBox.LostFocus events. On mobile, keyboard is always shown when text box has focus, so it will work nicely.

Force JScrollPane and JPanel to repaint

I have a JScrollPane that holds a JPanel. The layout on the JPanel is a GridBagLayout. On that JPanel, I add a number of custom components - each is a JPanel with 3 JLabels.
The first time in the program I lay all of this out, it works fine. When I invoke the code to add another custom component to the JPanel, the panel appears empty, but I can determine by examining the contents of the JPanel that my components are actually there. If I resize the JDialog in which this all sites, the JPanel will paint properly. It also works if I scroll the JScrollPane horizontally even a tiny bit.
I use the same method for the initial layout as I do when adding an item.
I've tried various combinations of repaint(), invalidate() and doLayout() but nothing seems to work all the time. I've run into this situation before and have never been able to fully solve it. Any suggestions?
Running under OpenJDK 7u25. Below is the code that lays out the scroll pane and panel.
private void displayRelatedBug(ArrayList<Bug> a_bugs) {
// sort the bugs by ID
ArrayList<Bug> l_sorted = new ArrayList<>(a_bugs);
Collections.sort(l_sorted);
pnlRelatedBugs.removeAll();
pnlRelatedBugs.setLayout(new GridBagLayout());
GridBagConstraints l_gbc = new GridBagConstraints();
l_gbc.gridx = 0;
l_gbc.gridy = 0;
l_gbc.gridwidth = 1;
l_gbc.gridheight = 1;
l_gbc.anchor = GridBagConstraints.NORTHWEST;
l_gbc.fill = GridBagConstraints.NONE;
l_gbc.insets = new Insets(3, 4, 0, 0);
for (Bug r : l_sorted) {
pnlRelatedBugs.add(new RelatedBugDisplay(r, this), l_gbc);
l_gbc.gridy++;
}
// add a filler at the bottom to push it up
l_gbc.weighty = 1.0;
pnlRelatedBugs.add(new MMPanel(), l_gbc);
// add a filler on the right to push them left
l_gbc.weighty = 0.0;
l_gbc.weightx = 1.0;
l_gbc.gridx++;
pnlRelatedBugs.add(new MMPanel(), l_gbc);
// try in vain to make it show up!!!
pnlRelatedBugs.invalidate();
pnlRelatedBugs.doLayout();
pnlRelatedBugs.repaint();
scrollerRelatedBugs.doLayout();
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
pnlRelatedBugs.repaint();
scrollerRelatedBugs.repaint();
// this seems to help if the scroll bar is showing
scrollerRelatedBugs.getHorizontalScrollBar().setValue(1);
scrollerRelatedBugs.getHorizontalScrollBar().setValue(0);
}
});
}
Whenever you add/remove components from a visible panel, the basic code is:
panel.remove(...);
panel.add(...);
panel.revalidate();
panel.repaint();
Without a proper SSCCE we can't really tell what your code is doing.
If you do add/remove/replace/others actions with components on showing container, you must to revalidate and repaint your container, to which you add components for proper displaying.

Detect tap in page?

I have a PhoneApplicationPage with some grids, images and a few buttons. If I tap outside my buttons, anywhere in the page (on an image, grid or whatever), I want to open a new page.
How can I detect a tap/click anywhere on the page?
I see at least two ways to do that:
Listen to the MouseLeftButtonUp event on your PhoneApplicationPage. It should be triggered by images and labels but not by buttons
Listen to the Tap event on your PhoneApplicationPage. However, this event will be triggered even when the user tap on a button. To prevent this, you can retrieve the list of controls at the tap coordinates in the event handler, and open the new page only if there's no button:
private void PhoneApplicationPage_Tap(object sender, System.Windows.Input.GestureEventArgs e)
{
var element = (UIElement)sender;
var controls = VisualTreeHelper.FindElementsInHostCoordinates(e.GetPosition(element), element);
if(controls.OfType<Button>().Any())
{
return;
}
// Open the new page
}

How to create customize title bar with close button on jFrame?

I want to create a customised title bar for my JFrame. I can remove the default title bar with
JFrame.setUndecorated(true)
Now i need to create a customised title bar for my JFrame with a close button?
Without having done that ever, I think I would go this way:
Indeed set the JFrame to undecorated
Extend JRootPane to add an additional field titleBar
Create a TitleBar component holding the title, the close button, etc...
Set a new LayoutManager on that JRootPane (have a look at JRootPane.RootLayout) and layout the components in the appropriate order (first the title bar, then below the menubar, then below the content pane)
Set an instance of that extends RootPane on your JFrame
There are maybe better ways.
I'm not quite sure of how you want to customize the close button, but maybe this can point you in the right direction: How can I customize the title bar on JFrame?
EDIT: Here's an updated working link to a forum about customizing his GUI and one user posted code on his creation of a simple GUI: Here
It looks like you can just modify his removeComponents method and create an addComponents method to fit your needs.
The Code According to the Above Link :
(Edited for Java 8)
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.logging.Level;
import java.util.logging.Logger;
class Testing {
public void buildGUI() throws UnsupportedLookAndFeelException {
JFrame.setDefaultLookAndFeelDecorated(true);
JFrame f = new JFrame();
f.setResizable(false);
removeMinMaxClose(f);
JPanel p = new JPanel(new GridBagLayout());
JButton btn = new JButton("Exit");
p.add(btn, new GridBagConstraints());
f.getContentPane().add(p);
f.setSize(400, 300);
f.setLocationRelativeTo(null);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.setVisible(true);
btn.addActionListener((ActionEvent ae) -> {
System.exit(0);
});
}
public void removeMinMaxClose(Component comp) {
if (comp instanceof AbstractButton) {
comp.getParent().remove(comp);
}
if (comp instanceof Container) {
Component[] comps = ((Container) comp).getComponents();
for (int x = 0, y = comps.length; x < y; x++) {
removeMinMaxClose(comps[x]);
}
}
}
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> {
try {
new Testing().buildGUI();
} catch (UnsupportedLookAndFeelException ex) {
Logger.getLogger(Testing.class.getName()).log(Level.SEVERE, null, ex);
}
});
}
}
may Work Fine but what if user also Want to set a L&F
such as nimbus
There are really three ways to approach this:
Set the frame to undecorated and implement everything, which includes control buttons, snapping, resizing and moving.
Get the root pane of the JFrame and directly edit that pane. You will need to add the control buttons and the snapping behaviour.
Use JNI to get the window's handle at the creation of a JFrame to get the control of it's attributes. This is better explained in this post. I have also built a little project which is basically an extension of the JFrame class that handles everything that needs to be dealt with... This last approach does not break native functions like snapping and resizing. But you do need to create the control buttons again since you have a new title bar if you want to build it from scratch.