温馨提示×

Debian上Fortran如何进行图形界面开发

小樊
38
2025-12-06 23:45:14
栏目: 智能运维

Debian上Fortran图形界面开发路线

一、路线总览与选型

  • 原生GUI(推荐):使用 GTK-Fortran(GTK+ 3) 构建本地桌面应用,控件丰富、跨桌面、社区活跃。适合需要窗口、按钮、菜单、绘图区等完整GUI的科学/工程软件。
  • 快速绘图与科研出图:使用 PGPLOT(基于X11/PostScript等)做二维科学绘图,安装简单、上手快,适合“计算+绘图”的场景(非完整GUI)。
  • 商业/Windows生态:使用 Winteracter(支持 Fortran 90/95,提供Windows与Linux版本),适合已有Fortran代码快速迁移到带GUI的应用。

二、方案一 GTK-Fortran 原生GUI(GTK+ 3)

  • 安装编译与依赖
    • 安装工具链与库:sudo apt update && sudo apt install -y gfortran build-essential cmake libgtk-3-dev
    • 获取与构建GTK-Fortran(示例):
      • git clone https://github.com/fortran-lang/gtk-fortran
      • cd gtk-fortran && mkdir build && cd build
      • cmake -DCMAKE_INSTALL_PREFIX=/usr/local …
      • make -j$(nproc) && sudo make install
  • 最小示例 app.f90(窗口+按钮)
    • 说明:使用GTK 3的 GtkApplicationGtkBuilder(UI文件)构建界面;按钮点击后改变标签文本。
    • 保存为 app.f90 与 window.ui(见下)。
    • 编译(pkg-config方式):gfortran app.f90 -o app pkg-config --cflags --libs gtk-3.0
  • 运行:./app

文件 window.ui(放在与 app.f90 同目录)

<?xml version="1.0" encoding="UTF-8"?>
<interface>
  <object class="GtkApplicationWindow" id="main_window">
    <property name="title">Fortran GTK3 示例</property>
    <property name="default-width">320</property>
    <property name="default-height">200</property>
    <child>
      <object class="GtkBox" id="vbox">
        <property name="orientation">vertical</property>
        <property name="spacing">6</property>
        <child>
          <object class="GtkLabel" id="label">
            <property name="label">Hello, Fortran!</property>
          </object>
        </child>
        <child>
          <object class="GtkButton" id="button">
            <property name="label">点击我</property>
            <signal name="clicked" handler="on_button_clicked" object="main_window"/>
          </object>
        </child>
      </object>
    </child>
  </object>
</interface>

文件 app.f90

program main
  use, intrinsic :: iso_c_binding
  implicit none
  interface
     ! 最小化GTK API声明(仅示例用)
     function gtk_init(argc, argv) bind(c, name="gtk_init")
       import :: c_int, c_ptr
       integer(c_int), value :: argc, argv
     end function gtk_init

     function g_application_new(app_id, flags) bind(c, name="g_application_new")
       import :: c_ptr, c_char
       character(kind=c_char), intent(in) :: app_id(*)
       integer(c_int), value :: flags
       type(c_ptr) :: g_application_new
     end function g_application_new

     function gtk_application_window_new(app) bind(c, name="gtk_application_window_new")
       import :: c_ptr
       type(c_ptr), value :: app
       type(c_ptr) :: gtk_application_window_new
     end function gtk_application_window_new

     function gtk_builder_new() bind(c, name="gtk_builder_new")
       import :: c_ptr
       type(c_ptr) :: gtk_builder_new
     end function gtk_builder_new

     function gtk_builder_add_from_file(builder, filename, error) &
          bind(c, name="gtk_builder_add_from_file")
       import :: c_ptr, c_char
       type(c_ptr), value :: builder
       character(kind=c_char), intent(in) :: filename(*)
       type(c_ptr), value :: error
       integer(c_int) :: gtk_builder_add_from_file
     end function gtk_builder_add_from_file

     function gtk_builder_get_object(builder, name) bind(c, name="gtk_builder_get_object")
       import :: c_ptr, c_char
       type(c_ptr), value :: builder
       character(kind=c_char), intent(in) :: name(*)
       type(c_ptr) :: gtk_builder_get_object
     end function gtk_builder_get_object

     subroutine gtk_label_set_text(label, text) bind(c, name="gtk_label_set_text")
       import :: c_ptr, c_char
       type(c_ptr), value :: label
       character(kind=c_char), intent(in) :: text(*)
     end subroutine gtk_label_set_text

     function g_signal_connect_data(instance, detailed_signal, c_handler, data, destroy_data, connect_flags) &
          bind(c, name="g_signal_connect_data")
       import :: c_ptr, c_int
       type(c_ptr), value :: instance, c_handler, data
       integer(c_int), value :: connect_flags
       type(c_ptr), value :: destroy_data
       integer(c_int) :: g_signal_connect_data
     end function g_signal_connect_data

     subroutine gtk_widget_show_all(widget) bind(c, name="gtk_widget_show_all")
       import :: c_ptr
       type(c_ptr), value :: widget
     end subroutine gtk_widget_show_all

     function g_application_run(app, argc, argv) bind(c, name="g_application_run")
       import :: c_int, c_ptr
       type(c_ptr), value :: app
       integer(c_int), value :: argc, argv
       integer(c_int) :: g_application_run
     end function g_application_run

     subroutine g_object_unref(obj) bind(c, name="g_object_unref")
       import :: c_ptr
       type(c_ptr), value :: obj
     end subroutine g_object_unref
  end interface

  ! UI元素句柄
  type(c_ptr) :: app, win, builder, label
  integer(c_int) :: status

  ! 初始化
  status = gtk_init(0, 0)

  ! 创建应用与窗口
  app = g_application_new("org.example.GtkFortran"//c_null_char, 0)
  win = gtk_application_window_new(app)

  ! 使用GtkBuilder加载UI
  builder = gtk_builder_new()
  status = gtk_builder_add_from_file(builder, "window.ui"//c_null_char, c_null_ptr)
  label = gtk_builder_get_object(builder, "label"//c_null_char)

  ! 连接信号:按钮点击 -> on_button_clicked
  call g_signal_connect_data(win, "destroy"//c_null_char, c_funloc(gtk_main_quit), c_null_ptr, c_null_ptr, 0)
  call g_signal_connect_data(gtk_builder_get_object(builder, "button"//c_null_char), &
       "clicked"//c_null_char, c_funloc(on_button_clicked), label, c_null_ptr, 0)

  ! 显示界面
  call gtk_widget_show_all(win)

  ! 运行主循环
  status = g_application_run(app, 0, c_null_ptr)

  ! 清理
  call g_object_unref(builder)
  call g_object_unref(app)

contains
  subroutine on_button_clicked(widget, data) bind(c)
    type(c_ptr), value :: widget, data
    call gtk_label_set_text(data, "按钮已被点击!"//c_null_char)
  end subroutine on_button_clicked

  subroutine gtk_main_quit(widget, data) bind(c)
    type(c_ptr), value :: widget, data
  end subroutine gtk_main_quit
end program main

三、方案二 PGPLOT 快速二维绘图(非完整GUI)

  • 适用:数值计算后快速出图(曲线、散点、柱状图等),基于 X11/PS/PDF 等设备输出。
  • 安装与配置
    • 安装依赖与编译器:sudo apt install -y gfortran libx11-dev
    • 下载并编译PGPLOT(示例):
      • 假设源码在 /usr/local/src/pgplot5.2.tar.gz
      • cd /usr/local/src && tar zxvf pgplot5.2.tar.gz
      • mkdir -p /usr/local/pgplot && cd /usr/local/pgplot
      • cp /usr/local/src/pgplot/drivers.list .
      • 编辑 drivers.list,取消注释需要设备(如 /XWINDOW/PS/CPS 等)
      • 在 /usr/local/pgplot 中运行:/usr/local/src/pgplot/makemake /usr/local/src/pgplot linux gfortran_gcc
      • 修改生成的 Makefile,将 FCOMPL = g77 改为 FCOMPL = gfortran
      • make && make cpg && make clean
    • 设置环境变量(写入 ~/.bashrc 或 ~/.zshrc):
      • export PGPLOT_DIR=/usr/local/pgplot
      • export PGPLOT_DEV=/Xserve # 使用X11窗口设备;也可设为/PS、/PDF等
  • 测试与编译示例
    • 运行自带示例:/usr/local/pgplot/pgdemo1(应弹出X11绘图窗口或在指定设备中生成文件)
    • 编译自己的绘图程序(示例):gfortran -o plot_demo plot_demo.f90 -L/usr/local/pgplot -lpgplot -lX11
  • 说明:PGPLOT上手快、适合科研绘图;若需要复杂交互与控件,请选择原生GUI方案。

四、方案三 Winteracter 商业方案(Windows/Linux)

  • 特点:面向 Fortran 90/95 的商业GUI工具集,提供窗口、对话框、控件、OpenGL 3D、打印、帮助系统等,适合希望快速获得成熟GUI且兼顾跨平台的团队。
  • 获取与安装:前往 Winteracter 官网获取发行包并按其文档安装;Linux 下同样提供库与示例工程。
  • 适用场景:已有大型Fortran代码库,期望以较少改动获得现代GUI与交互能力。

五、开发工具与构建建议

  • 编译器与构建:使用 gfortran;原生GUI建议配合 CMake 管理依赖与构建(便于定位头文件与库路径)。
  • IDE与编辑器:可用 VS Code(配合Fortran扩展与CMake Tools)或 Code::Blocks(跨平台IDE,支持C/C++/Fortran),提升编辑、构建与调试效率。

0