Window Only Renders correctly on first show - gtk

I have a window that I am opening like so
if (Window == null) {
var con = WindowType.GetConstructor(new Type[0]);
Window = (PopupWindow)con.Invoke(new object[0]);
//The types are subclasses of PopupWindow.
Window.Controller = this;
Window.Show ();
}
This correctly displays the window as long as it is the first of these windows to pop up... If I close the window and create an entirely new one, the window is just a grey area until I restart debugging... Any ideas?
public PopupWindow () : base(Gtk.WindowType.Toplevel)
{
this.AppPaintable = true;
this.Colormap = this.Screen.RgbaColormap;
this.Events = Gdk.EventMask.AllEventsMask;
this.Decorated = false;
this.SkipTaskbarHint = true;
}
Example subclass
public StorageWindow () : base()
{
this.Build ();
this.Move (this.Screen.Width - 428, 55);
//set some label props.
StorageCircle.ExposeEvent += (o, args) => {
//Draw a circle
};
}
P.S. This is how I am destroying the window.
if (Window != null) {
Window.Destroy();
Window = null;
}

The entire issue turned out to be caused by a non gtk timer trying to edit widgets outside of the main thread.

Related

Why jzy3/jogl newt window is always on top?

I'm using jzy3d/SWT with mapper and surface and this code to create the chart (container is a composite with gridLayout) :
Settings.getInstance().setHardwareAccelerated(true);
jzy3DChart = SWTChartComponentFactory.chart(container);
((CanvasNewtSWT)jzy3DChart.getCanvas()).setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
jzy3DChart.black();
jzy3DChart.getScene().getGraph().add(surface);
ChartLauncher.openChart(jzy3DChart);
I get this rendering at initial creation :
But when another part is selected, the newt window always stay on top (chart3 is 2D chart and should be on top) :
I've tried to toggle newt window visibility using :
newtCanvasSWT.getNEWTChild().setVisible(false/true);
But doing so the newt window becomes independent and no longer embedded in its SWT container and can disappear under other controls when it should not.
What am I doing wrong ?
How to set newt window not to be always on top ?
Edit :
Here is the workaround code I've used :
getSite().getPage().addPartListener(new IPartListener2() {
#Override
public void partHidden(IWorkbenchPartReference partRef) {
// Dispose jsyz3d chart composite when this part is hidden
if(partRef.getPart(false) == XYZChartEditor.this) {
if(chart != null) {
chart.dispose();
chart = null;
}
}
}
#Override
public void partVisible(IWorkbenchPartReference partRef) {
// Refresh or rebuild chart when this part reappears
if(partRef.getPart(false) == XYZChartEditor.this) {
if(chart != null) {
// Force chart parent composite to layout
chartContainer.layout();
return;
}
// Rebuild chart
chart = SWTChartFactory.chart(chartContainer, Quality.Nicest());
chart.getView().setViewPoint(xyzChartData.getViewPoint());
chart.getView().addViewPointChangedListener(XYZChartEditor.this);
chart.black();
ChartLauncher.openChart(chart);
// Force chart parent composite to layout
chartContainer.layout();
boolean wasDirty = XYZChartEditor.this.isDirty();
SelectionChangedEvent event = new SelectionChangedEvent(trialsListViewer, trialsListViewer.getSelection());
XYZChartEditor.this.selectionChanged(event);
if(!wasDirty) XYZChartEditor.this.setDirty(false);
((CanvasNewtSWT)chart.getCanvas()).addMouseListener(XYZChartEditor.this);
canvas = ((CanvasNewtSWT) chart.getCanvas());
newtCanvasSWT = canvas.getCanvas();
newtWindow = ((CanvasNewtSWT) chart.getCanvas()).getCanvas().getNEWTChild();
}
}
});

gtk_container_add: assertion 'GTK_IS_WIDGET (widget)' failed

public class Epoch.MainWindow : Gtk.ApplicationWindow {
private Gtk.Grid grid;
private Epoch.LabelsGrid labels;
private Epoch.PreferencesView preferences_view;
private Epoch.MainView main_view;
public MainWindow (Application app) {
Object (
application: app,
icon_name: "com.github.Suzie97.epoch",
resizable: false,
title: _("Epoch"),
width_request: 500
);
}
construct {
get_style_context ().add_class ("rounded");
set_keep_below (true);
stick ();
var preferences_button = new Gtk.Button.from_icon_name ("open-menu-symbolic", Gtk.IconSize.SMALL_TOOLBAR);
preferences_button.valign = Gtk.Align.CENTER;
var preferences_stack = new Gtk.Stack ();
preferences_stack.add (preferences_view);
preferences_stack.add (main_view);
preferences_stack.transition_type = Gtk.StackTransitionType.SLIDE_LEFT;
var headerbar = new Gtk.HeaderBar ();
headerbar.show_close_button = true;
var headerbar_style_context = headerbar.get_style_context ();
headerbar_style_context.add_class ("default-decoration");
headerbar_style_context.add_class (Gtk.STYLE_CLASS_FLAT);
headerbar.pack_end (preferences_button);
set_titlebar (headerbar);
var main_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0);
main_box.pack_start (preferences_stack, true, true);
add (main_box);
show_all ();
preferences_view = new Epoch.PreferencesView ();
preferences_button.activate.connect (() => {
preferences_stack.visible_child = preferences_view;
});
// public override bool configure_event (Gdk.EventConfigure event) {
// int root_x, root_y;
// get_position (out root_x, out root_y);
// Epoch.settings.set_int ("window-x", root_x);
// Epoch.settings.set_int ("window-y", root_y);
// return base.configure_event (event);
}
}
The following error is displayed when I compile,
I want the app to switch to the preferences view when the button on the right side of the header bar is clicked,
Only, the headerbar is displayed when as you can see.
Why is this happening? How do I solve it?
preferences_stack.add (preferences_view);
preferences_stack.add (main_view);
You haven't initialized preferences_view yet, and you never initialize main_view. That's where your second and third errors are coming from: gtk_container_add() is complaining that the widget you are trying to add is not actually a widget, but rather null, because you haven't initialized that variable yet.

Gtk.Stack won't change visible child inside an event callback function

So I am currently working on an app for elementary os and encountered a problem.
I have a window which has a Granite.Sourcelistview on the left and a stack holding the different views on the right. My problem is that when pressing a button on one of the screens (the project settings screen i created), the stack should change the current view to a different one but it doesn't. The current view stays and is not changed.
This is the window:
public class MainWindow : Gtk.Window {
private SourceListStackView srcl_view {get; set;}
construct {
var header = new Gtk.HeaderBar ();
header.show_close_button = true;
//this is the source list view
srcl_view = new SourceListStackView ();
var paned = new Gtk.Paned (Gtk.Orientation.HORIZONTAL);
paned.position = 130;
paned.pack1 (srcl_view, false, false);
paned.add2 (srcl_view.stack);
add(paned);
set_titlebar (header);
}
public static int main(string[] args) {
Gtk.init (ref args);
MainWindow app = new MainWindow ();
app.show_all ();
Gtk.main ();
return 0;
}
}
This is the sourcelistview class that i created:
public class SourceListStackView : Granite.Widgets.SourceList {
public Gtk.Stack stack {get; set;}
public SourceListStackView () {
var project_page = new ProjectSettings ();
stack = new Gtk.Stack ();
var project = new Granite.Widgets.SourceList.ExpandableItem("Root");
this.root.add(project);
stack.add_named(project_page, "hello");
//here depending on what item of the sourcelist is created,
//the view with the same name as the item
//should be displayed (not the best mechanism but works)
this.item_selected.connect ((item) => {
if(item != null){
stack.visible_child_name = item.name;
}
});
//problematic part is here: This won't change the current view..why?
//The button should add another item to the
// source list view and change the current view
// to the newly created Welcome Screen but it doesn't do that..
project_page.button.clicked.connect(() => {
project.add(new Granite.Widgets.SourceList.Item ("Welcome"));
stack.add_named(new Granite.Widgets.Welcome("bla bli blu", "bla"), "Welcome");
stack.set_visible_child_name("Welcome");
});
}
}
This is the view with the button that should trigger the change of the view:
public class ProjectSettings : Granite.SimpleSettingsPage {
public Gtk.Button button {get; set;}
public ProjectSettings () {
Object (
activatable: false,
description: "This is a screen",
header: "",
icon_name: "preferences-system",
title: "Screen"
);
}
construct {
var project_name_label = new Gtk.Label ("Name");
project_name_label.xalign = 1;
var project_name_entry = new Gtk.Entry ();
project_name_entry.hexpand = true;
project_name_entry.placeholder_text = "Peter";
content_area.attach (project_name_label, 0, 0, 1, 1);
content_area.attach (project_name_entry, 1, 0, 1, 1);
button = new Gtk.Button.with_label ("Save Settings");
action_area.add (button);
}
}
The part that does not work is this one:
//problematic part is here: This won't change the current view.. why?
project_page.button.clicked.connect(() => {
project.add(new Granite.Widgets.SourceList.Item ("Welcome"));
stack.add_named(new Granite.Widgets.Welcome("bla bli blu", "bla"), "Welcome");
stack.set_visible_child_name("Welcome");
});
I do not know why it wont change the view. I specifically tell it to set the visible child to "Welcome" (and that is exactly how i named it one line above), but it just won't appear. Can someone explain to me why?
I can easily change the stack's visible child outside of the signal/event but inside of it won't do the trick..
Thanks a lot
Update: The issue was solved through José Fonte's comment down below: I instantiated the view, called the show_all () method on it and then added it to the stack and set the visible child to it.

JavaFx Showing popup is not working on client machine

Following is my code to show popup windows in my JavaFx Desktop Application.
public boolean popup(Object parent, ViewModelBase viewModel, AsyncCommand cancelCommand) {
javafx.scene.layout.Pane root = null;
try
{
if(!IOC.platformInfo.isPlatformThread())
{
return PlatformUtil.runAndWait(()->
{
return popup(parent,viewModel,cancelCommand);
});
}
String name = viewModel.getClass().getSimpleName();
name = Pattern.compile("(viewModel|Controller)$",Pattern.CASE_INSENSITIVE)
.matcher(name).replaceAll("View");
FXMLLoader loader = new FXMLLoader(com.technoinn.videoprospector.ui.fx.service.WindowService
.class.getResource(String.format("/fxml/%s.fxml",name))
, null, new JavaFXBuilderFactory(), new IocControllerFactory());
if(viewModel instanceof ControllerBase)
{
loader.setController(viewModel);
}
root = loader.load();
if(!(viewModel instanceof ControllerBase))
{
Object controller = loader.getController();
if(controller instanceof ControllerBase)
{
((ControllerBase)controller).setViewModel(viewModel);
}
}
jfxtras.scene.control.window.Window window =
new jfxtras.scene.control.window.Window(viewModel.getDisplayName());
window.getContentPane().getChildren().add(root);
window.setPrefSize(root.getPrefWidth(), root.getPrefHeight());
window.setMinSize(root.getPrefWidth(), root.getPrefHeight());
CloseIcon closeIcon = new CloseIcon(window);
window.getLeftIcons().add(closeIcon);
Scene scene = new Scene(window);
// Scene scene = new Scene(root);
scene.getStylesheets().add(FxModule.StyleFile);
Stage stage = new Stage(StageStyle.UNDECORATED);
stage.setResizable(true);
stage.setMinWidth(root.getPrefWidth());
stage.setMinHeight(root.getPrefHeight());
viewModel.addPropertyChangeListener(ViewModelBase.closeCommand,
(x)->
{
if(x.getNewValue()!=null && x.getNewValue()==Boolean.TRUE)
{
stage.close();
}
});
closeIcon.setCursor(Cursor.HAND);
closeIcon.setOnAction((x)->
{
if(cancelCommand!=null)
cancelCommand.beginExecution();
else
stage.close();
});
/*
stage.setOnCloseRequest((WindowEvent event) -> {
if(cancelCommand!=null)
cancelCommand.beginExecution();
else
stage.close();
});*/
stage.setScene(scene);
stage.centerOnScreen();
stage.initModality(Modality.APPLICATION_MODAL);
if(!parentWindows.isEmpty())
{
stage.initOwner(parentWindows.peek());
stage.initModality(Modality.WINDOW_MODAL);
}
parentWindows.push(stage);
stage.showAndWait();
parentWindows.pop();
}catch(Exception exp)
{
Logger.getGlobal().log(Level.SEVERE,"Error in popup",exp);
}
return true;
}
Problem is, popup shows well and in proper size on my machine.(Dev Machine). But size on target client machine is unpredictable. Sometimes it is very small and sometimes it does not even show the content pane of the popup window. Client machine has jRE 1.8_31. Any idea what can be wrong. Client machine size is same as that of my dev machine.
Thanks
Most probably you are calling next code too soon:
window.setPrefSize(root.getPrefWidth(), root.getPrefHeight());
window.setMinSize(root.getPrefWidth(), root.getPrefHeight());
and
stage.setMinWidth(root.getPrefWidth());
stage.setMinHeight(root.getPrefHeight());
Most layout values are being calculated only after scene is shown. Try to move such code after call to
stage.showAndWait();

gtk: how to hide a window when the application loses focus

I want to duplicate the behaviour of tool windows in OpenOfice. When the application loses focus, the tool windows (if they are not docked) are hidden.
So, I have a main window, and another utility window (win_dock). I want to hide win_dock when all the windows of the application loses focus and show it again if a window gain focus.
What I did is that I connected to the focus-in-event and focus-out-event of all windows of the application, and I maintain a counter of how many windows have focus. When this counter drops to zero, I want to hide win_dock, and if this counter is positive again, I want to show win_dock
The problem is with this solution I can never focus win_dock. Because when I click on it, the main window drops the focus, so it hides win_dock that still hadn't gained the focus. Nevertheless the focus-in-event is still sent to win_dock and the windows reappears. But in the meantime it has lost the focus.
Do you have a better solution?
Here is the Vala source code:
public class Main
{
private Gtk.Builder builder;
private Gtk.Window win_messages;
private Gtk.Window win_dock;
private int focus_count = 0;
public Main() {
builder = new Gtk.Builder();
builder.add_from_file("ui2.glade");
win_messages = builder.get_object("win_messages") as Gtk.Window;
win_dock = builder.get_object("win_dock") as Gtk.Window;
handle_focus(win_messages);
handle_focus(win_dock);
}
public void start(){
win_messages.show_all();
//win_dock.show_all();
Gtk.main();
}
private void handle_focus(Gtk.Window w) {
w.focus_in_event.connect ((w, e) => {
stdout.printf("Focus In (%s)\n", w.name);
focus_count++;
manage_focus(w == win_dock);
});
w.focus_out_event.connect((w, e) => {
stdout.printf("Focus Out (%s)\n", w.name);
focus_count--;
manage_focus(w == win_dock);
});
}
private void manage_focus(bool is_dock){
if(focus_count > 0) {
win_dock.show_all();
stdout.printf("Show (focus: %d)\n", focus_count);
} else if(is_dock) {
win_dock.hide_all();
stdout.printf("Hide (focus: %d, has: %d) dock\n", focus_count, win_dock.is_active ? 1 : 0);
} else if(!is_dock) {
if(win_dock.is_active) {
win_dock.hide_all();
stdout.printf("Hide (focus: %d, has: %d) !dock\n", focus_count, win_dock.is_active ? 1 : 0);
} else {
stdout.printf("Nop (focus: %d, has: %d) !dock\n", focus_count, win_dock.is_active ? 1 : 0);
}
}
}
public static int main (string[] args)
{
Gtk.init (ref args);
Main m = new Main();
m.start();
return 0;
}
}
Thanks.
Is there a good reason to make the dialog disappear? Wouldn't it be enough to make win_dock transient (win_dock.set_transient_for) for the main window?
Otherwise you could try using GLib.Idle.add to call manage_focuswhich will cause
manage_focus to run after all your focus event callbacks have run. It will then have the correct number of focused windows.