增加键盘ui

This commit is contained in:
2026-07-17 16:57:54 +08:00
parent e8183dfbc4
commit b067ffdc8e
3 changed files with 238 additions and 10 deletions
+58
View File
@@ -0,0 +1,58 @@
package ui
import (
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
)
func keyButton(label string, entry *widget.Entry) *widget.Button {
return widget.NewButton(label, func() {
entry.Append(label)
})
}
func entButton(entry *widget.Entry) *widget.Button {
return widget.NewButton("ENT", func() {
entry.Append("\n")
})
}
func clearButton(label string, entry *widget.Entry) *widget.Button {
return widget.NewButton(label, func() {
entry.SetText("")
})
}
func newIPKeypad(entry *widget.Entry) fyne.CanvasObject {
presets := container.NewHBox(
keyButton("192.168.", entry),
keyButton("169.254.", entry),
keyButton("10.", entry),
keyButton("100.", entry),
)
numpad := container.NewGridWithColumns(3,
keyButton("1", entry), keyButton("2", entry), keyButton("3", entry),
keyButton("4", entry), keyButton("5", entry), keyButton("6", entry),
keyButton("7", entry), keyButton("8", entry), keyButton("9", entry),
entButton(entry), keyButton("0", entry), keyButton(".", entry),
keyButton("/", entry), keyButton("-", entry), clearButton("清空IP", entry),
)
return container.NewVBox(presets, numpad)
}
func newPortKeypad(entry *widget.Entry) fyne.CanvasObject {
presets := container.NewGridWithColumns(3,
keyButton("1-65535", entry), keyButton("80;443", entry), keyButton("21", entry),
keyButton("22", entry), keyButton("23", entry), keyButton("3389", entry),
keyButton("445", entry), keyButton("25565", entry), keyButton("25;587", entry),
)
numpad := container.NewGridWithColumns(3,
keyButton("1", entry), keyButton("2", entry), keyButton("3", entry),
keyButton("4", entry), keyButton("5", entry), keyButton("6", entry),
keyButton("7", entry), keyButton("8", entry), keyButton("9", entry),
keyButton("0", entry), keyButton(";", entry), keyButton("-", entry),
entButton(entry), clearButton("清空端口", entry),
)
return container.NewVBox(presets, numpad)
}
+175
View File
@@ -0,0 +1,175 @@
package ui
import (
"fmt"
"net/url"
"strconv"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
"fyne.io/fyne/v2/widget"
)
const appVersion = "V1.5.1"
const (
ipPlaceholder = "例子:\n127.0.0.1 - 单IP\n192.168.0.0/24 - 掩码IP段\n0.0.0.0-255.255.255.255 - IP段\ndomain.com - 单域名"
portPlaceholder = "例子:\n22 - 单端口\n80;443 - 多个不连续端口\n3000-65535 - 连续的端口范围"
)
type scanForm struct {
app fyne.App
ipList *widget.Entry
portList *widget.Entry
timeout *widget.Entry
threads *widget.Entry
output *widget.Entry
progress *widget.ProgressBar
scanBtn *widget.Button
pingBtn *widget.Button
scanning bool
}
func newScanForm(app fyne.App) *scanForm {
f := &scanForm{app: app}
f.ipList = widget.NewMultiLineEntry()
f.ipList.SetPlaceHolder(ipPlaceholder)
f.ipList.SetMinRowsVisible(4)
f.portList = widget.NewMultiLineEntry()
f.portList.SetPlaceHolder(portPlaceholder)
f.portList.SetMinRowsVisible(4)
f.timeout = newIntEntry(100, 1, 10000)
f.threads = newIntEntry(64, 1, 1024)
f.output = widget.NewMultiLineEntry()
f.output.SetMinRowsVisible(6)
f.progress = widget.NewProgressBar()
f.scanBtn = widget.NewButton("开始扫描", f.toggleScan)
f.pingBtn = widget.NewButton("仅Ping", f.togglePing)
return f
}
func (f *scanForm) build() fyne.CanvasObject {
ipSection := container.NewVBox(
widget.NewLabel("IP"),
f.ipList,
newIPKeypad(f.ipList),
)
portSection := container.NewVBox(
widget.NewLabel("端口"),
f.portList,
newPortKeypad(f.portList),
)
topRow := container.New(layout.NewGridLayoutWithColumns(2), ipSection, portSection)
controlRow := f.buildControlRow()
topArea := container.NewVBox(topRow, controlRow)
footer := container.NewHBox(
widget.NewLabel(appVersion),
layout.NewSpacer(),
widget.NewButton("Blog", func() { f.openURL("https://wnfed.com/") }),
widget.NewButton("GitLab", func() { f.openURL("https://git.lmve.net/kevin/tcp_ip_scan") }),
widget.NewButton("GitHub", func() { f.openURL("https://github.com/wuwenfengmi1998/tcp_ip_scan") }),
)
return container.NewBorder(topArea, footer, nil, nil, f.output)
}
func (f *scanForm) buildControlRow() fyne.CanvasObject {
left := container.NewHBox(
widget.NewButton("清空输出", func() { f.output.SetText("") }),
widget.NewButton("保存输出", f.saveOutput),
container.NewHBox(widget.NewLabel("超时ms"), f.timeout),
container.NewHBox(widget.NewLabel("线程"), f.threads),
widget.NewButton("清空IP", func() { f.ipList.SetText("") }),
f.pingBtn,
)
right := container.NewHBox(
widget.NewButton("清空端口", func() { f.portList.SetText("") }),
f.scanBtn,
)
return container.NewBorder(nil, nil, left, right, f.progress)
}
func (f *scanForm) toggleScan() {
if !f.scanning {
f.scanning = true
f.scanBtn.SetText("停止扫描")
f.pingBtn.Disable()
f.setInputsEnabled(false)
f.progress.SetValue(0)
f.output.Append("开始扫描... (TODO: 接入扫描逻辑)\n")
} else {
f.scanning = false
f.scanBtn.SetText("开始扫描")
f.pingBtn.Enable()
f.setInputsEnabled(true)
f.output.Append("已停止扫描\n")
}
}
func (f *scanForm) togglePing() {
if !f.scanning {
f.scanning = true
f.pingBtn.SetText("停止Ping")
f.scanBtn.Disable()
f.setInputsEnabled(false)
f.progress.SetValue(0)
f.output.Append("开始Ping... (TODO: 接入扫描逻辑)\n")
} else {
f.scanning = false
f.pingBtn.SetText("仅Ping")
f.scanBtn.Enable()
f.setInputsEnabled(true)
f.output.Append("已停止Ping\n")
}
}
func (f *scanForm) setInputsEnabled(enabled bool) {
if enabled {
f.ipList.Enable()
f.portList.Enable()
f.timeout.Enable()
f.threads.Enable()
} else {
f.ipList.Disable()
f.portList.Disable()
f.timeout.Disable()
f.threads.Disable()
}
}
func (f *scanForm) saveOutput() {
f.output.Append("(TODO: 保存输出到文件)\n")
}
func (f *scanForm) openURL(urlStr string) {
u, err := url.Parse(urlStr)
if err != nil {
return
}
_ = f.app.OpenURL(u)
}
func newIntEntry(val, min, max int) *widget.Entry {
e := widget.NewEntry()
e.SetText(strconv.Itoa(val))
e.Validator = func(s string) error {
n, err := strconv.Atoi(s)
if err != nil || n < min || n > max {
return fmt.Errorf("需为 %d-%d", min, max)
}
return nil
}
return e
}
+5 -10
View File
@@ -3,24 +3,19 @@ package ui
import ( import (
"fyne.io/fyne/v2" "fyne.io/fyne/v2"
"fyne.io/fyne/v2/app" "fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/widget"
) )
const ( const (
appTitle = "IP Scanner" appTitle = "TCP端口扫描工具"
appWidth = 800 appWidth = 850
appHeight = 600 appHeight = 500
) )
func Run() { func Run() {
a := app.New() a := app.New()
f := newScanForm(a)
w := a.NewWindow(appTitle) w := a.NewWindow(appTitle)
w.SetContent(f.build())
w.SetContent(container.NewVBox(
widget.NewLabel("Hello Fyne!"),
))
w.Resize(fyne.NewSize(appWidth, appHeight)) w.Resize(fyne.NewSize(appWidth, appHeight))
w.ShowAndRun() w.ShowAndRun()
} }