Hiatus

I’ve accomplished what I set out to do — I’ve created a GUI application using C#/Gtk# that demonstrates at least basic usage of some common controls (“widgets”).

I’ve learned a lot during this process, including about some significant differences between this environment and those I’ve previously programmed in.

Curiously, I didn’t learn much about C# itself. Most of the difficult stuff was done within Gtk#/GTK+ or the Mono framework. I often implemented a widget feature with only one line of code.

As I wrote in my first post, I welcome comments, especially from those more knowledgeable than myself. I’d like to know if I’ve done anything that violates “best practices” for programming in this environment.

I may restart this blog if I decide to work on a “real” programming project. Until then, this blog is on hiatus while I do other things.

(For the curious, one of those other things is my music.)

Until next time…happy programming!

Advertisements
Posted in Programming | Leave a comment

The Spin Button

I’m going to add a spin button to my application.

I research class SpinButton. It seems pretty easy!

I open MonoDevelop, select the existing Demo project, and go to the GUI Designer.

I drag a Spin Button widget to the HBox section immediately to the right of the calendar. The spin button doesn’t appear to have a label. That’s OK for this application but something to be aware of for the future.

The default values for the spin button (e.g., a range of 0-100) seem OK. The only thing I’m going to do is to display the spin button’s value.

I change the spin button’s Widget name to spnMain and create a signal handler for the ValueChanged signal named OnSpin.

I write the OnSpin code as follows:

protected virtual void OnSpin (object sender, System.EventArgs e)
{
    DisplayEvent ("Spin " + spnMain.ValueAsInt);
}

I test the code (such as it is) and it works!

The Demo application now looks like this:

Posted in Programming | Leave a comment

The Calendar Widget

I’m going to add a calendar to my application. I read the help for the Calendar class and decide that clicking a day on the calendar will display the selected date.

I open MonoDevelop, select the existing Demo project, and go to the GUI Designer.

I insert a new section into the existing VBox. I then drag a HBox to the upper available section of the VBox. I then drag a Calendar widget to the left section of the new HBox.

I set the Widget name for the calendar to calMain. I create a signal handler for DaySelected named OnDay.

I write the OnDay method based on what I learned in the help.

protected virtual void OnDay (object sender, System.EventArgs e)
{
    string dateString = calMain.GetDate ().ToString ("MM/dd/yyyy");
    DisplayEvent ("Date " + dateString);
}

I run the program; it works the first time!

Note that I used the U.S. date format of month/day/year; feel free to change the format string.

Posted in Programming | Leave a comment

A Brief Word About Debugging

Unfortunately, the version of MonoDevelop I’m using (2.2.1) doesn’t have a debugger. When I run into a problem I use the WriteLine method of the Console class to display information I’m interested in. The information is displayed in MonoDevelop’s Application Output window.

For example, I added a temporary call to WriteLine in the OnPercentage method that I wrote in the previous post:

protected virtual void OnPercentage (object sender, System.EventArgs e)
{
    const int msDelay = 25;

    for (int pct = 0; pct <= 100; pct++)
    {
        prgMain.Fraction = ((double) pct / 100.0);
        prgMain.Text = (pct + "%");
Console.WriteLine ("pct = " + pct + "  Fraction = " + prgMain.Fraction);

        // Force the program to redraw the progress bar.
        Main.IterationDo (false);

        // Wait a while.
        System.Threading.Thread.Sleep (msDelay);
    }

    prgMain.Text = "Done";
}

When run, this produces output in the Application Output window:

The Console class is part of the System namespace. I could have specified System.Console.WriteLine but didn’t need to reference System. because the source file includes the line

using System;

at the beginning of the file.

Posted in Programming | 1 Comment

Progress Bar

I’m going to add a progress bar to the Demo application.

I research the ProgressBar class and find that a progress bar has two modes: percentage mode and activity mode. Percentage mode is used when the program knows how far through a process it is. Activity mode is used when the program doesn’t know that but wants to indicate that something is happening.

The help contains an example program for percentage mode that I’ll use as a guide.

I open MonoDevelop, select the existing Demo project, and go to the GUI Designer.

I insert a new section in the VBox. I drag a HBox to the lower empty VBox section (immediately above the Cancel and OK buttons). I drag a Button to the left section of this HBox, another Button to the center section, and a Progress Bar to the right section.

I set the Widget name of the progress bar to prgMain.

For the left button, I set Widget name to cmdPercent and Label to Pe_rcentage.

For the right button, I set Widget name to cmdActivity and Label to _Activity.

For each of the buttons I create a Clicked signal handler (OnPercentage and OnActivity, respectively).

The window now looks like this in the Designer:

I write the OnPercentage method similar to the example in the help.

protected virtual void OnPercentage (object sender, System.EventArgs e)
{
    const int lowerBound = 0;
    const int upperBound = 100;

    prgMain.Adjustment.Lower = lowerBound;
    prgMain.Adjustment.Upper = upperBound;

    for (int pct = lowerBound; pct <= upperBound; pct++)
    {
        prgMain.Adjustment.Value = pct;
        prgMain.Text = (pct + "%");
    }

    prgMain.Text = "Done";
}

I then run the program and click the Percentage button.

The entire bar fills in a fraction of a second (this was not unexpected). I assume that there must be a time delay method somewhere in the Mono framework, and there is: System.Threading.Thread.Sleep. I call that method with a parameter of 25ms and run the program again.

protected virtual void OnPercentage (object sender, System.EventArgs e)
{
    const int msDelay = 25;
    const int lowerBound = 0;
    const int upperBound = 100;

    prgMain.Adjustment.Lower = lowerBound;
    prgMain.Adjustment.Upper = upperBound;

    for (int pct = lowerBound; pct <= upperBound; pct++)
    {
        prgMain.Adjustment.Value = pct;
        prgMain.Text = (pct + "%");

        // Wait a while.
        System.Threading.Thread.Sleep (msDelay);
    }

    prgMain.Text = "Done";
}

It takes the right amount of time to get to 100% but doesn’t show anything in between!

I determine that the progress bar has to be able to process events in order to update itself. I’m using the progress bar in a way that doesn’t allow it to get any events. After more research, I find I can call Main.IterationDo in order to allow the progress bar to get events.

protected virtual void OnPercentage (object sender, System.EventArgs e)
{
    const int msDelay = 25;
    const int lowerBound = 0;
    const int upperBound = 100;

    prgMain.Adjustment.Lower = lowerBound;
    prgMain.Adjustment.Upper = upperBound;

    for (int pct = lowerBound; pct <= upperBound; pct++)
    {
        prgMain.Adjustment.Value = pct;
        prgMain.Text = (pct + "%");

        // Force the program to redraw the progress bar.
        Main.IterationDo (false);

        // Wait a while.
        System.Threading.Thread.Sleep (msDelay);
    }

    prgMain.Text = "Done";
}

I run the program again and verify that it works.

I now write the OnActivity method, using the Pulse method to move the progress bar.

protected virtual void OnActivity (object sender, System.EventArgs e)
{
    const int msDelay = 80;

    prgMain.Text = "Please wait...";

    for (int i = 0; i < 50; i++)
    {
        prgMain.Pulse ();

        // Force the program to redraw the progress bar.
        Main.IterationDo (false);

        // Wait a while.
        System.Threading.Thread.Sleep (msDelay);
    }

    prgMain.Text = "";
}

It works, except it doesn’t clear the progress bar when done. I also notice that the percentage feature doesn’t work properly after the activity feature has been used (the bar still looks like it does in activity mode). I eventually find that setting the Fraction property to 0 is a solution for both issues.

protected virtual void OnActivity (object sender, System.EventArgs e)
{
    const int msDelay = 80;

    prgMain.Text = "Please wait...";

    for (int i = 0; i < 50; i++)
    {
        prgMain.Pulse ();

        // Force the program to redraw the progress bar.
        Main.IterationDo (false);

        // Wait a while.
        System.Threading.Thread.Sleep (msDelay);
    }

    prgMain.Text = "";
    prgMain.Fraction = 0;
}

Here’s what the progress bar looks like in activity mode:

My research leads me to conclude that I should have used the Fraction property in the OnPercentage method to set the bar’s position instead of using Adjustment.Value. I used Adjustment.Value because that’s what the example program in the help did. However, every other example I found used Fraction instead of Adjustment.Value. Reading more closely, the help indicates to use the Fraction property, contradicting the example on the same page.

The Adjustment.Value property is an integer that ranges between the values of the Adjustment.Lower and Adjustment.Upper properties. The Fraction property is a double ranging between 0.0 and 1.0. I change the OnPercentage method to use Fraction and find that I can shorten the code.

protected virtual void OnPercentage (object sender, System.EventArgs e)
{
    const int msDelay = 25;

    for (int pct = 0; pct <= 100; pct++)
    {
        prgMain.Fraction = ((double) pct / 100.0);
        prgMain.Text = (pct + "%");

        // Force the program to redraw the progress bar.
        Main.IterationDo (false);

        // Wait a while.
        System.Threading.Thread.Sleep (msDelay);
    }

    prgMain.Text = "Done";
}

On an unrelated note, I notice that somewhere along the line the radio button group that I had painstaking aligned has now moved to the center of the screen. Another mystery!

Posted in Programming | 1 Comment

The Combo Box

I plan to add a combo box (a drop-down list) to the project. The combo box will allow me to select between several Ubuntu-related distributions.

I research the ComboBox class. I’m interested in using the ActiveText property, probably invoked from the Changed signal.

Note that there’s also a Combo Box Entry widget (class ComboBoxEntry), which is similar (ComboBoxEntry derives from class ComboBox). However, I’ll only be using the regular Combo Box widget.

I open MonoDevelop, select the existing Demo project, and go to the GUI Designer.

I drag a Combo Box widget to the empty space below the two check boxes. I set Widget name to cboDist. Under Combo Box Properties, I click on the Items entry and then on the “” button at the far right. In the main text box, I enter the following:

Ubuntu
Kubuntu
Xubuntu

I then click the OK button.

I run the program and verify that the entries are present; however, there’s no default value. I review the properties and set Active item to 0 (the list index associated with the first entry in the list). I run the program and verify that Ubuntu is now the default value.

I create a handler for the Changed signal and name it OnDist. I add one line to the OnDist method:

protected virtual void OnDist (object sender, System.EventArgs e)
{
    DisplayEvent ("Distribution " + cboDist.ActiveText);
}

The program now displays the selected entry.

The program now looks like this (with the combo box closed and open):

Posted in Programming | Leave a comment

The About Dialog

I want my application to have an “About” box. I do my research and find that there’s an AboutDialog class in Gtk#. The documentation has an example program that I can use as a guide (unfortunately, I later found it to be somewhat out-of-date).

I open MonoDevelop, select the existing Demo project, and go to the GUI Designer.

I add a new menu _Help with a new entry _About. I set the Activated signal for the _About entry to execute a handler method named OnAbout.

I write the OnAbout method as follows:

protected virtual void OnAbout (object sender, System.EventArgs e)
{
    AboutDialog dialog = new AboutDialog ();

    dialog.ProgramName = "Demo Application";
    dialog.Version = "0.0.1";
    dialog.Comments = "Gtk# Demo Application";
    dialog.Authors = new string [] {"Steven L. Grace"};
    dialog.Website = "http://www.google.com/";

    dialog.Run ();
}

I run the program and select the About box. It looks like this:

I’m pleasantly surprised that the web site link works; the documentation suggested that additional work would be involved. The only thing that doesn’t work is the Close box.

After some additional research and experimentation, I find the answer. Clicking the Close button returns control to the program but leaves the About dialog still displayed. I call the dialog’s Destroy method to remove the dialog.

protected virtual void OnAbout (object sender, System.EventArgs e)
{
    AboutDialog dialog = new AboutDialog ();

    dialog.ProgramName = "Demo Application";
    dialog.Version = "0.0.1";
    dialog.Comments = "Gtk# Demo Application";
    dialog.Authors = new string [] {"Steven L. Grace"};
    dialog.Website = "http://www.google.com/";

    dialog.Run ();
    dialog.Destroy ();
}

(Note that it probably would have been possible to have defined the About dialog elsewhere, have the OnAbout handler call the Run method to display the dialog, and then call the Hide method to close the dialog.)

Posted in Programming | Leave a comment