GTK2 +自动调整按钮标签的字体大小

时间:2015-11-29 02:07:18

标签: c gtk gtk2

我正在做一个Tic-Tac-Toe游戏作为学校项目。我在3行中设置了9个按钮,因此每当用户点击其中一个按钮时,其标签就会以纯文本形式更改为X或O.

enter image description here

我想知道X / O的大小是否可能根据窗口的大小而改变。我的另一个想法是使用X / O而不是纯文本的图像(至少因为我假设如果我使用大图像它会自动缩小);我不是真的想这样做,因为检查玩家赢得游戏的功能比较标签'文本。

这是负责创建和添加按钮的代码:

GtkWidget *button;
button = gtk_button_new_with_label("");
gtk_box_pack_start(GTK_BOX(theBox),button,FALSE,TRUE,0);
g_signal_connect(GTK_OBJECT(button),"clicked",GTK_SIGNAL_FUNC(ButtonClicked),EntryBox);
gtk_widget_show(button);

这是我的ButtonClicked功能:

void ButtonClicked(GtkButton *button, gpointer data)
{
  if (strcmp(gtk_button_get_label(button), "") == 0)
    if (count % 2 != 0)
      gtk_button_set_label(button, "X");
}

另外,虽然我在这里,但还有另外一个问题:我将窗口边框设置为0但你仍然可以看到很少的边框,有什么方法可以摆脱它吗?

1 个答案:

答案 0 :(得分:0)

您可以试试这个,我使用"expose-event"绘制XO以及一个空单元格,以防用户尚未点击它并且还使用了简单的功能来检查胜利者。通过将数据传递给事件处理程序来设置单元格值。

"button-release-event"允许您在单击某个单元格时执行某些操作,然后您可以将下一轮转到另一个玩家,并将XO设置为所单击的单元格,具体取决于当它被陈词滥调时哪个玩家转过来。

检查

#include <gtk/gtk.h>

#include <stdlib.h>
#include <math.h>

enum Player
{
    FirstPlayer,
    SecondPlayer
};

enum TicTacValue
{
    None,
    Empty,
    Unset,
    X,
    O
};

struct GameData
{
    enum TicTacValue value;
    enum Player *player;
    struct GameData *data;
    gint row;
    gint column;
};

enum TicTacValue
evaluate(enum TicTacValue previous, enum TicTacValue next)
{
    if (previous == Unset)
        return next;
    if (previous != next)
        return None;
    return next;
}

void
check_winner(struct GameData *data)
{
    enum TicTacValue rows[3] = {Unset, Unset, Unset};
    enum TicTacValue diagonals[2] = {Unset, Unset};
    enum TicTacValue columns[3] = {Unset, Unset, Unset};
    enum TicTacValue winner;

    for (size_t i = 0 ; i < 9 ; ++i)
    {
        columns[i % 3] = evaluate(columns[i % 3], data[i].value);
        rows[i / 3] = evaluate(rows[i / 3], data[i].value);
        switch (i)
        {
            case 4:
                diagonals[0] = evaluate(diagonals[0], data[i].value);
                diagonals[1] = evaluate(diagonals[1], data[i].value);
                break;
            case 0:
            case 8:
                diagonals[0] = evaluate(diagonals[0], data[i].value);
                break;
            case 2:
            case 6:
                diagonals[1] = evaluate(diagonals[1], data[i].value);
                break;
        }
    }

    winner = diagonals[0] | diagonals[1];
    winner = winner | columns[0] | columns[1] | columns[2];
    winner = winner | rows[0] | rows[1] | rows[2];
    if (winner < Unset)
        return;
    fprintf(stderr, "Player %d WINS (-)\n", winner - Unset);
}

gboolean
on_click(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
    struct GameData *game_data;
    game_data = (struct GameData *) data;
    if (game_data->value != Empty)
        return FALSE;
    if (*(game_data->player) == FirstPlayer)
    {
        game_data->value = X;
        *(game_data->player) = SecondPlayer;
    }
    else
    {
        game_data->value = O;
        *(game_data->player) = FirstPlayer;
    }
    gtk_widget_queue_draw(widget);
    check_winner(game_data->data);
    return FALSE;
}

void
draw_delmiter_line(cairo_t *cairo, gint x1, gint y1, gint x2, gint y2)
{
    cairo_save(cairo);
    cairo_set_source_rgb(cairo, 0.65, 0.65, 0.65);
    cairo_set_antialias(cairo, CAIRO_ANTIALIAS_NONE);
    cairo_set_line_width(cairo, 1);
    cairo_move_to(cairo, x1, y1);
    cairo_line_to(cairo, x2, y2);
    cairo_stroke(cairo);
    cairo_restore(cairo);
}

void
draw_x(cairo_t *cairo, gint width, gint height)
{
    gint size;

    size = width / 3.5;

    cairo_save(cairo);
    cairo_set_source_rgb(cairo, 0.25, 0.4, 1.0);
    cairo_set_line_width(cairo, 2.5);
    cairo_translate(cairo, width / 2, height / 2);
    cairo_move_to(cairo, -size, -size);
    cairo_line_to(cairo, +size, +size);
    cairo_move_to(cairo, +size, -size);
    cairo_line_to(cairo, -size, +size);
    cairo_stroke(cairo);
    cairo_restore(cairo);
}

void
draw_o(cairo_t *cairo, gint width, gint height)
{
    cairo_save(cairo);
    cairo_set_source_rgb(cairo, 1.0, 0.25, 0.25);
    cairo_set_line_width(cairo, 2.5);
    cairo_arc(cairo, width / 2, height / 2, width / 3, 0, 2.0 * M_PI);
    cairo_stroke(cairo);
    cairo_restore(cairo);
}

gboolean
on_expose(GtkWidget *widget, GdkEventExpose *event, gpointer data)
{
    GdkWindow *window;
    cairo_t *cairo;
    const struct GameData *game_data;
    gint width;
    gint height;

    window = gtk_widget_get_window(widget);
    cairo = gdk_cairo_create(window);
    game_data = (const struct GameData *) data;

    gdk_window_get_size(window, &width, &height);

    if (game_data->row != 2)
        draw_delmiter_line(cairo, 0, height, width, height);
    if (game_data->column != 3)
        draw_delmiter_line(cairo, width, 0, width, height);

    if (game_data->value == X)
        draw_x(cairo, width, height);
    else if (game_data->value == O)
        draw_o(cairo, width, height);
    cairo_destroy(cairo);
    return FALSE;
}

int
main(int argc, char **argv)
{
    GtkWidget *window;
    GtkWidget *horizontal[3];
    GtkWidget *vertical;
    struct GameData data[9];
    enum Player current_player;
    gtk_init(&argc, &argv);

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    vertical = gtk_vbox_new(TRUE, 0);
    for (size_t i = 0 ; i < 3 ; ++i)
    {
        horizontal[i] = gtk_hbox_new(TRUE, 0);
        gtk_box_pack_start(GTK_BOX(vertical), horizontal[i], TRUE, TRUE, 0);
    }

    current_player = FirstPlayer;
    for (size_t i = 0 ; i < 9 ; ++i)
    {
        GtkWidget *cell;

        cell = gtk_drawing_area_new();
        data[i].value = Empty;
        data[i].player = &current_player;
        data[i].data = data;
        data[i].row = i / 3;
        data[i].column = i % 3;

        g_signal_connect(G_OBJECT(cell), "expose-event", G_CALLBACK(on_expose), &data[i]);
        g_signal_connect(G_OBJECT(cell), "button-release-event", G_CALLBACK(on_click), &data[i]);

        gtk_widget_add_events(cell, GDK_BUTTON_RELEASE_MASK | GDK_BUTTON_PRESS_MASK);
        gtk_box_pack_start(GTK_BOX(horizontal[data[i].row]), cell, TRUE, TRUE, 0);
    }
    g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);

    gtk_container_add(GTK_CONTAINER(window), vertical);
    gtk_widget_set_size_request(window, 300, 300);
    gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
    gtk_widget_show_all(window);
    gtk_main();

    return 0;
}