我正在尝试用 mpb 制作两行进度条。
假设我有一个包含文件绝对路径的切片。
list := []string{"c:temp01.png", "c:temp02.png", "c:temp03.png", "c:temptest.png", "c:temptest01.png"}
我希望它像这样显示:
processing 01.png ...
0 / 5 [ ] 0%
processing 02.png ...
1 / 5 [== ] 20%
processing 03.png ...
2 / 5 [==== ] 40%
等等。
将“正在处理...”部分和进度条分开的原因是:
- 我想显示有关当前处理状态的附加信息。
processing 01.png ... [mode: webp] 0 / 5 [ ] 0%
- 有时,我必须处理同一个文件两次。
processing 01.mp4 ... [mode: webm] [pass: 1/2] 0 / 5 [ ] 0%
请注意,进度条未更改。processing 01.mp4 ... [mode: webm] [pass: 2/2] 0 / 5 [ ] 0%
- 我也想一次制作多个进度条。
当事情发生变化时,每个进度条都应该尽快更新,而不是“每 0.5 秒更新每个进度条”。Processing 01.mp4 ... [Mode: WebM] [Pass: 1/2] 4 / 5 [================ ] 0% Processing 01.png ... [Mode: WebP] 2 / 5 [======== ] 0% Processing DONE [Mode: MP3] 5 / 5 [====================] 100%
我找不到这样做的方法。 mpb 的每个示例代码都是在单行中完成其工作。
正确答案
我第一次看到这个库,但在探索了一些代码之后,我发现了如何根据我们的需要添加新的和自定义的栏。我对您在评论中提供的链接示例进行了一些修改,以演示添加和自定义栏。
package main
import (
"fmt"
"io"
"math/rand"
"time"
"github.com/vbauerster/mpb/v8"
"github.com/vbauerster/mpb/v8/decor"
)
func main() {
p := mpb.new()
var piece, piece2 int64
var way, way2 int64
file := func(_ decor.statistics) string {
return "file.extension "
}
file2 := func(_ decor.statistics) string {
return "file2.extension "
}
part := func(s decor.statistics) string {
s.current = piece
s.total = 5
return fmt.sprintf(" part %d/%d", s.current, s.total)
}
part2 := func(s decor.statistics) string {
s.current = piece2
s.total = 10
return fmt.sprintf(" part %d/%d", s.current, s.total)
}
pass := func(s decor.statistics) string {
s.current = way
s.total = 2
return fmt.sprintf(" pass %d/%d", s.current, s.total)
}
pass2 := func(s decor.statistics) string {
s.current = way2
s.total = 4
return fmt.sprintf(" pass %d/%d", s.current, s.total)
}
var total = 100
bar := p.new(int64(total),
mpb.nopstyle(), // make main bar style nop, so there are just decorators
mpb.barextender(extended(mpb.barstyle().build()), false), // extend wtih normal bar on the next line
mpb.prependdecorators(
decor.any(file),
decor.name("percentage: "),
decor.newpercentage("%d"),
decor.any(part),
decor.any(pass),
),
)
bar2 := p.new(int64(total+100),
mpb.nopstyle(),
mpb.barextender(extended(mpb.barstyle().build()), false),
mpb.prependdecorators(
decor.any(file2),
decor.name("percentage: "),
decor.newpercentage("%d"),
decor.any(part2),
decor.any(pass2),
),
)
// simulating some work
max := 100 * time.millisecond
for i := 0; i < total+100; i++ {
switch {
case i == 20 || i == 40 || i == 60 ||
i == 80 || i == 100 || i == 120 ||
i == 140 || i == 160 || i == 180:
piece2++
if i == 100 {
way2++
piece = 5
way = 2
} else if i < 100 {
piece++
}
case i == 50 || i == 150:
if i < 100 {
way++
}
way2++
}
time.sleep(time.duration(rand.intn(10)+1) * max / 10)
if i < 100 {
bar.increment()
}
bar2.increment()
}
way2 = 4
piece2 = 10
// wait for our bar to complete and flush
p.wait()
}
func extended(base mpb.barfiller) mpb.barfiller {
return mpb.barfillerfunc(func(w io.writer, st decor.statistics) error {
err := base.fill(w, st)
if err != nil {
return err
}
_, err = io.writestring(w, "n")
return err
})
}
假设您已经知道如何制作自定义装饰器。
要创建一个新栏,您可以执行以下操作:
bar := p.new(int64(total),
mpb.nopstyle(), // make main bar style nop, so there are just decorators
mpb.barextender(extended(mpb.barstyle().build()), false), // extend wtih normal bar on the next line
mpb.prependdecorators(
decor.any(file),
decor.name("percentage: "),
decor.newpercentage("%d"),
decor.any(part),
decor.any(pass),
),
)
例如,我只制作了两个金条,但您制作了两个以上。
在这个示例中,为了演示如何制作新栏,我使用了 new()
方法,但经过一些研究后,我发现还有更多方法可以制作新栏。区别主要在于酒吧的外观。您可以通过在 progress 结构的方法列表中查找返回 bar
实例的方法来找到它们nofollow noreferrer">文档。
p.new()
的第一个参数用于定义条形的总值,在该条形中为 100。
只需将您的装饰器/部分放入 mpb.prependdecorators
或 mpb.appenddecorators
即可。
mpb.prependdecorators(
decor.any(file),
decor.name("percentage: "),
decor.newpercentage("%d"),
decor.any(part),
decor.any(pass),
),
您可以为每个栏使用相同的装饰器,但我建议为每个栏创建新的装饰器以避免发生冲突的可能性。
这将分别显示文件名、百分比、部分和通过:
file.extension percentage: 100% part 5/5 pass 2/2
[==============================================================================]
在此示例中,每个装饰都会根据其循环中的设置值增加 1,循环遍历条形的总值。在这个栏中,我只是迭代了 1 到 100。我的目标是 100 到 5 个部分。当循环变量遇到100中的5个部分之一时,条形的part
装饰会增加1。
而当达到50时,pass
装饰就会增加1。
for i := 0; i < total+100; i++ {
switch {
case i == 20 || i == 40 || i == 60 ||
i == 80 || i == 100 || i == 120 ||
i == 140 || i == 160 || i == 180:
piece2++
if i == 100 {
way2++
piece = 5
way = 2
} else if i < 100 {
piece++
}
case i == 50 || i == 150:
if i < 100 {
way++
}
way2++
}
time.sleep(time.duration(rand.intn(10)+1) * max / 10)
if i < 100 {
bar.increment()
}
bar2.increment()
}
这个循环也适用于第二个小节。我只是将两个条形的增量状态组合在一个循环中以使代码更短。如果循环变量小于 100,则增加第一个柱的状态。当它达到100时,将所有装饰全部增加到总数,然后继续增加第二个栏的状态,直到循环结束。循环完成后,完成第二个条形增量的其余部分以达到总计。
65bd2e1fcfff第二个栏包含 10 个零件和 4 个通道,总价值为 200。
整个代码的输出是:
file.extension percentage: 9% part 0/5 pass 0/2
[======>-----------------------------------------------------------------------]
file2.extension percentage: 4% part 0/10 pass 0/4
[===>--------------------------------------------------------------------------]
file.extension percentage: 49% part 2/5 pass 0/2
[=====================================>----------------------------------------]
file2.extension percentage: 24% part 2/10 pass 0/4
[==================>-----------------------------------------------------------]
file.extension percentage: 100% part 5/5 pass 2/2
[==============================================================================]
file2.extension percentage: 74% part 7/10 pass 2/4
[=========================================================>--------------------]
file.extension Percentage: 100% Part 5/5 Pass 2/2
[==============================================================================]
file2.extension Percentage: 100% Part 10/10 Pass 4/4
[==============================================================================]